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/cctest/wasm/test-run-wasm-64.cc b/test/cctest/wasm/test-run-wasm-64.cc
index 784f21a..333183a 100644
--- a/test/cctest/wasm/test-run-wasm-64.cc
+++ b/test/cctest/wasm/test-run-wasm-64.cc
@@ -24,20 +24,14 @@
 
 #define asu64(x) static_cast<uint64_t>(x)
 
-#define B2(a, b) kExprBlock, 2, a, b
-#define B1(a) kExprBlock, 1, a
+#define B2(a, b) kExprBlock, a, b, kExprEnd
+#define B1(a) kExprBlock, a, kExprEnd
 
 // Can't bridge macro land with nested macros.
-#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_X87
-#define MIPS_OR_X87 true
+#if V8_TARGET_ARCH_MIPS
+#define MIPS true
 #else
-#define MIPS_OR_X87 false
-#endif
-
-#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_X87 || V8_TARGET_ARCH_ARM
-#define MIPS_OR_ARM_OR_X87 true
-#else
-#define MIPS_OR_ARM_OR_X87 false
+#define MIPS false
 #endif
 
 #define FOREACH_I64_OPERATOR(V) \
@@ -47,9 +41,9 @@
   V(I64Return, true)            \
   V(I64Param, true)             \
   V(I64LoadStore, true)         \
-  V(I64Add, !MIPS_OR_X87)       \
-  V(I64Sub, !MIPS_OR_X87)       \
-  V(I64Mul, !MIPS_OR_X87)       \
+  V(I64Add, true)               \
+  V(I64Sub, true)               \
+  V(I64Mul, !MIPS)              \
   V(I64DivS, true)              \
   V(I64DivU, true)              \
   V(I64RemS, true)              \
@@ -57,9 +51,9 @@
   V(I64And, true)               \
   V(I64Ior, true)               \
   V(I64Xor, true)               \
-  V(I64Shl, !MIPS_OR_X87)       \
-  V(I64ShrU, !MIPS_OR_X87)      \
-  V(I64ShrS, !MIPS_OR_X87)      \
+  V(I64Shl, true)               \
+  V(I64ShrU, true)              \
+  V(I64ShrS, true)              \
   V(I64Eq, true)                \
   V(I64Ne, true)                \
   V(I64LtS, true)               \
@@ -72,7 +66,7 @@
   V(I64GeU, true)               \
   V(I64Ctz, true)               \
   V(I64Clz, true)               \
-  V(I64Popcnt, !MIPS_OR_X87)    \
+  V(I64Popcnt, true)            \
   V(I32ConvertI64, true)        \
   V(I64SConvertF32, true)       \
   V(I64SConvertF64, true)       \
@@ -96,7 +90,7 @@
 #define REQUIRE(name) \
   if (!WASM_64 && !kSupported_##name) return
 
-TEST(Run_Wasm_I64Const) {
+WASM_EXEC_TEST(I64Const) {
   REQUIRE(I64Const);
   WasmRunner<int64_t> r;
   const int64_t kExpectedValue = 0x1122334455667788LL;
@@ -105,7 +99,7 @@
   CHECK_EQ(kExpectedValue, r.Call());
 }
 
-TEST(Run_Wasm_I64Const_many) {
+WASM_EXEC_TEST(I64Const_many) {
   REQUIRE(I64Const);
   int cntr = 0;
   FOR_INT32_INPUTS(i) {
@@ -118,19 +112,16 @@
   }
 }
 
-TEST(Run_Wasm_Return_I64) {
+WASM_EXEC_TEST(Return_I64) {
   REQUIRE(I64Return);
   WasmRunner<int64_t> r(MachineType::Int64());
 
-  BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0)));
+  BUILD(r, WASM_RETURN1(WASM_GET_LOCAL(0)));
 
   FOR_INT64_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
 }
 
-// todo(ahaas): I added a list of missing instructions here to make merging
-// easier when I do them one by one.
-// kExprI64Add:
-TEST(Run_WasmI64Add) {
+WASM_EXEC_TEST(I64Add) {
   REQUIRE(I64Add);
   WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -138,8 +129,8 @@
     FOR_INT64_INPUTS(j) { CHECK_EQ(*i + *j, r.Call(*i, *j)); }
   }
 }
-// kExprI64Sub:
-TEST(Run_Wasm_I64Sub) {
+
+WASM_EXEC_TEST(I64Sub) {
   REQUIRE(I64Sub);
   WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -147,10 +138,8 @@
     FOR_INT64_INPUTS(j) { CHECK_EQ(*i - *j, r.Call(*i, *j)); }
   }
 }
-// kExprI64Mul:
-// kExprI64DivS:
 
-TEST(Run_WasmI64DivS) {
+WASM_EXEC_TEST(I64DivS) {
   REQUIRE(I64DivS);
   WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -167,7 +156,7 @@
   }
 }
 
-TEST(Run_WasmI64DivS_Trap) {
+WASM_EXEC_TEST(I64DivS_Trap) {
   REQUIRE(I64DivS);
   WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -178,7 +167,7 @@
   CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), asi64(0)));
 }
 
-TEST(Run_WasmI64DivS_Byzero_Const) {
+WASM_EXEC_TEST(I64DivS_Byzero_Const) {
   REQUIRE(I64DivS);
   for (int8_t denom = -2; denom < 8; denom++) {
     WasmRunner<int64_t> r(MachineType::Int64());
@@ -192,9 +181,8 @@
     }
   }
 }
-// kExprI64DivU:
 
-TEST(Run_WasmI64DivU) {
+WASM_EXEC_TEST(I64DivU) {
   REQUIRE(I64DivU);
   WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64());
   BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -209,7 +197,7 @@
   }
 }
 
-TEST(Run_WasmI64DivU_Trap) {
+WASM_EXEC_TEST(I64DivU_Trap) {
   REQUIRE(I64DivU);
   WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64());
   BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -219,7 +207,7 @@
   CHECK_TRAP64(r.Call(std::numeric_limits<uint64_t>::max(), asu64(0)));
 }
 
-TEST(Run_WasmI64DivU_Byzero_Const) {
+WASM_EXEC_TEST(I64DivU_Byzero_Const) {
   REQUIRE(I64DivU);
   for (uint64_t denom = 0xfffffffffffffffe; denom < 8; denom++) {
     WasmRunner<uint64_t> r(MachineType::Uint64());
@@ -234,8 +222,8 @@
     }
   }
 }
-// kExprI64RemS:
-TEST(Run_WasmI64RemS) {
+
+WASM_EXEC_TEST(I64RemS) {
   REQUIRE(I64RemS);
   WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -250,7 +238,7 @@
   }
 }
 
-TEST(Run_WasmI64RemS_Trap) {
+WASM_EXEC_TEST(I64RemS_Trap) {
   REQUIRE(I64RemS);
   WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -261,8 +249,7 @@
   CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), asi64(0)));
 }
 
-// kExprI64RemU:
-TEST(Run_WasmI64RemU) {
+WASM_EXEC_TEST(I64RemU) {
   REQUIRE(I64RemU);
   WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64());
   BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -277,7 +264,7 @@
   }
 }
 
-TEST(Run_Wasm_I64RemU_Trap) {
+WASM_EXEC_TEST(I64RemU_Trap) {
   REQUIRE(I64RemU);
   WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64());
   BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -287,8 +274,7 @@
   CHECK_TRAP64(r.Call(std::numeric_limits<uint64_t>::max(), asu64(0)));
 }
 
-// kExprI64And:
-TEST(Run_Wasm_I64And) {
+WASM_EXEC_TEST(I64And) {
   REQUIRE(I64And);
   WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_AND(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -296,8 +282,8 @@
     FOR_INT64_INPUTS(j) { CHECK_EQ((*i) & (*j), r.Call(*i, *j)); }
   }
 }
-// kExprI64Ior:
-TEST(Run_Wasm_I64Ior) {
+
+WASM_EXEC_TEST(I64Ior) {
   REQUIRE(I64Ior);
   WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_IOR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -305,8 +291,8 @@
     FOR_INT64_INPUTS(j) { CHECK_EQ((*i) | (*j), r.Call(*i, *j)); }
   }
 }
-// kExprI64Xor:
-TEST(Run_Wasm_I64Xor) {
+
+WASM_EXEC_TEST(I64Xor) {
   REQUIRE(I64Xor);
   WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -314,8 +300,8 @@
     FOR_INT64_INPUTS(j) { CHECK_EQ((*i) ^ (*j), r.Call(*i, *j)); }
   }
 }
-// kExprI64Shl:
-TEST(Run_Wasm_I64Shl) {
+
+WASM_EXEC_TEST(I64Shl) {
   REQUIRE(I64Shl);
   {
     WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64());
@@ -349,8 +335,8 @@
     FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 40, r.Call(*i)); }
   }
 }
-// kExprI64ShrU:
-TEST(Run_Wasm_I64ShrU) {
+
+WASM_EXEC_TEST(I64ShrU) {
   REQUIRE(I64ShrU);
   {
     WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64());
@@ -384,8 +370,8 @@
     FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 40, r.Call(*i)); }
   }
 }
-// kExprI64ShrS:
-TEST(Run_Wasm_I64ShrS) {
+
+WASM_EXEC_TEST(I64ShrS) {
   REQUIRE(I64ShrS);
   {
     WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
@@ -419,8 +405,8 @@
     FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 40, r.Call(*i)); }
   }
 }
-// kExprI64Eq:
-TEST(Run_Wasm_I64Eq) {
+
+WASM_EXEC_TEST(I64Eq) {
   REQUIRE(I64Eq);
   WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_EQ(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -428,8 +414,8 @@
     FOR_INT64_INPUTS(j) { CHECK_EQ(*i == *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
-// kExprI64Ne:
-TEST(Run_Wasm_I64Ne) {
+
+WASM_EXEC_TEST(I64Ne) {
   REQUIRE(I64Ne);
   WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_NE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -437,8 +423,8 @@
     FOR_INT64_INPUTS(j) { CHECK_EQ(*i != *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
-// kExprI64LtS:
-TEST(Run_Wasm_I64LtS) {
+
+WASM_EXEC_TEST(I64LtS) {
   REQUIRE(I64LtS);
   WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_LTS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -446,7 +432,8 @@
     FOR_INT64_INPUTS(j) { CHECK_EQ(*i < *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
-TEST(Run_Wasm_I64LeS) {
+
+WASM_EXEC_TEST(I64LeS) {
   REQUIRE(I64LeS);
   WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_LES(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -454,7 +441,8 @@
     FOR_INT64_INPUTS(j) { CHECK_EQ(*i <= *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
-TEST(Run_Wasm_I64LtU) {
+
+WASM_EXEC_TEST(I64LtU) {
   REQUIRE(I64LtU);
   WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_LTU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -462,7 +450,8 @@
     FOR_UINT64_INPUTS(j) { CHECK_EQ(*i < *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
-TEST(Run_Wasm_I64LeU) {
+
+WASM_EXEC_TEST(I64LeU) {
   REQUIRE(I64LeU);
   WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_LEU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -470,7 +459,8 @@
     FOR_UINT64_INPUTS(j) { CHECK_EQ(*i <= *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
-TEST(Run_Wasm_I64GtS) {
+
+WASM_EXEC_TEST(I64GtS) {
   REQUIRE(I64GtS);
   WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_GTS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -478,7 +468,8 @@
     FOR_INT64_INPUTS(j) { CHECK_EQ(*i > *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
-TEST(Run_Wasm_I64GeS) {
+
+WASM_EXEC_TEST(I64GeS) {
   REQUIRE(I64GeS);
   WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_GES(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -487,7 +478,7 @@
   }
 }
 
-TEST(Run_Wasm_I64GtU) {
+WASM_EXEC_TEST(I64GtU) {
   REQUIRE(I64GtU);
   WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_GTU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -496,7 +487,7 @@
   }
 }
 
-TEST(Run_Wasm_I64GeU) {
+WASM_EXEC_TEST(I64GeU) {
   REQUIRE(I64GeU);
   WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_GEU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -504,8 +495,8 @@
     FOR_UINT64_INPUTS(j) { CHECK_EQ(*i >= *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
-// kExprI32ConvertI64:
-TEST(Run_Wasm_I32ConvertI64) {
+
+WASM_EXEC_TEST(I32ConvertI64) {
   REQUIRE(I32ConvertI64);
   FOR_INT64_INPUTS(i) {
     WasmRunner<int32_t> r;
@@ -513,29 +504,22 @@
     CHECK_EQ(static_cast<int32_t>(*i), r.Call());
   }
 }
-// kExprI64SConvertI32:
-TEST(Run_Wasm_I64SConvertI32) {
+
+WASM_EXEC_TEST(I64SConvertI32) {
   REQUIRE(I64SConvertI32);
   WasmRunner<int64_t> r(MachineType::Int32());
   BUILD(r, WASM_I64_SCONVERT_I32(WASM_GET_LOCAL(0)));
   FOR_INT32_INPUTS(i) { CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i)); }
 }
 
-// kExprI64UConvertI32:
-TEST(Run_Wasm_I64UConvertI32) {
+WASM_EXEC_TEST(I64UConvertI32) {
   REQUIRE(I64UConvertI32);
   WasmRunner<int64_t> r(MachineType::Uint32());
   BUILD(r, WASM_I64_UCONVERT_I32(WASM_GET_LOCAL(0)));
   FOR_UINT32_INPUTS(i) { CHECK_EQ(static_cast<uint64_t>(*i), r.Call(*i)); }
 }
 
-// kExprF64ReinterpretI64:
-// kExprI64ReinterpretF64:
-
-// kExprI64Clz:
-// kExprI64Ctz:
-// kExprI64Popcnt:
-TEST(Run_WasmI64Popcnt) {
+WASM_EXEC_TEST(I64Popcnt) {
   struct {
     int64_t expected;
     uint64_t input;
@@ -552,15 +536,14 @@
   }
 }
 
-// kExprF32SConvertI64:
-TEST(Run_WasmF32SConvertI64) {
+WASM_EXEC_TEST(F32SConvertI64) {
   REQUIRE(F32SConvertI64);
   WasmRunner<float> r(MachineType::Int64());
   BUILD(r, WASM_F32_SCONVERT_I64(WASM_GET_LOCAL(0)));
   FOR_INT64_INPUTS(i) { CHECK_FLOAT_EQ(static_cast<float>(*i), r.Call(*i)); }
 }
-// kExprF32UConvertI64:
-TEST(Run_WasmF32UConvertI64) {
+
+WASM_EXEC_TEST(F32UConvertI64) {
   REQUIRE(F32UConvertI64);
   struct {
     uint64_t input;
@@ -647,15 +630,15 @@
     CHECK_EQ(bit_cast<float>(values[i].expected), r.Call(values[i].input));
   }
 }
-// kExprF64SConvertI64:
-TEST(Run_WasmF64SConvertI64) {
+
+WASM_EXEC_TEST(F64SConvertI64) {
   REQUIRE(F64SConvertI64);
   WasmRunner<double> r(MachineType::Int64());
   BUILD(r, WASM_F64_SCONVERT_I64(WASM_GET_LOCAL(0)));
   FOR_INT64_INPUTS(i) { CHECK_DOUBLE_EQ(static_cast<double>(*i), r.Call(*i)); }
 }
-// kExprF64UConvertI64:
-TEST(Run_Wasm_F64UConvertI64) {
+
+WASM_EXEC_TEST(F64UConvertI64) {
   REQUIRE(F64UConvertI64);
   struct {
     uint64_t input;
@@ -741,9 +724,8 @@
     CHECK_EQ(bit_cast<double>(values[i].expected), r.Call(values[i].input));
   }
 }
-// kExprI64SConvertF32:
 
-TEST(Run_Wasm_I64SConvertF32a) {
+WASM_EXEC_TEST(I64SConvertF32a) {
   WasmRunner<int64_t> r(MachineType::Float32());
   BUILD(r, WASM_I64_SCONVERT_F32(WASM_GET_LOCAL(0)));
 
@@ -756,8 +738,8 @@
     }
   }
 }
-// kExprI64SConvertF64:
-TEST(Run_Wasm_I64SConvertF64a) {
+
+WASM_EXEC_TEST(I64SConvertF64a) {
   WasmRunner<int64_t> r(MachineType::Float64());
   BUILD(r, WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(0)));
 
@@ -771,8 +753,7 @@
   }
 }
 
-// kExprI64UConvertF32:
-TEST(Run_Wasm_I64UConvertF32a) {
+WASM_EXEC_TEST(I64UConvertF32a) {
   WasmRunner<uint64_t> r(MachineType::Float32());
   BUILD(r, WASM_I64_UCONVERT_F32(WASM_GET_LOCAL(0)));
 
@@ -786,8 +767,7 @@
   }
 }
 
-// kExprI64UConvertF64:
-TEST(Run_Wasm_I64UConvertF64a) {
+WASM_EXEC_TEST(I64UConvertF64a) {
   WasmRunner<uint64_t> r(MachineType::Float64());
   BUILD(r, WASM_I64_UCONVERT_F64(WASM_GET_LOCAL(0)));
 
@@ -801,7 +781,7 @@
   }
 }
 
-TEST(Run_WasmCallI64Parameter) {
+WASM_EXEC_TEST(CallI64Parameter) {
   // Build the target function.
   LocalType param_types[20];
   for (int i = 0; i < 20; i++) param_types[i] = kAstI64;
@@ -822,8 +802,8 @@
     WasmRunner<int32_t> r(&module);
     BUILD(
         r,
-        WASM_I32_CONVERT_I64(WASM_CALL_FUNCTION(
-            index, WASM_I64V_9(0xbcd12340000000b),
+        WASM_I32_CONVERT_I64(WASM_CALL_FUNCTIONN(
+            19, index, WASM_I64V_9(0xbcd12340000000b),
             WASM_I64V_9(0xbcd12340000000c), WASM_I32V_1(0xd),
             WASM_I32_CONVERT_I64(WASM_I64V_9(0xbcd12340000000e)),
             WASM_I64V_9(0xbcd12340000000f), WASM_I64V_10(0xbcd1234000000010),
@@ -875,7 +855,7 @@
       TestI64Binop(kExpr##name, expected, a, b); \
   } while (false)
 
-TEST(Run_Wasm_I64Binops) {
+WASM_EXEC_TEST(I64Binops) {
   TEST_I64_BINOP(I64Add, -5586332274295447011, 0x501b72ebabc26847,
                  0x625de9793d8f79d6);
   TEST_I64_BINOP(I64Sub, 9001903251710731490, 0xf24fe6474640002e,
@@ -912,7 +892,7 @@
     if (WASM_64 || kSupported_##name) TestI64Cmp(kExpr##name, expected, a, b); \
   } while (false)
 
-TEST(Run_Wasm_I64Compare) {
+WASM_EXEC_TEST(I64Compare) {
   TEST_I64_CMP(I64Eq, 0, 0xB915D8FA494064F0, 0x04D700B2536019A3);
   TEST_I64_CMP(I64Ne, 1, 0xC2FAFAAAB0446CDC, 0x52A3328F780C97A3);
   TEST_I64_CMP(I64LtS, 0, 0x673636E6306B0578, 0x028EC9ECA78F7227);
@@ -925,7 +905,7 @@
   TEST_I64_CMP(I64GeU, 0, 0x0886A0C58C7AA224, 0x5DDBE5A81FD7EE47);
 }
 
-TEST(Run_Wasm_I64Clz) {
+WASM_EXEC_TEST(I64Clz) {
   REQUIRE(I64Clz);
   struct {
     int64_t expected;
@@ -971,7 +951,7 @@
   }
 }
 
-TEST(Run_Wasm_I64Ctz) {
+WASM_EXEC_TEST(I64Ctz) {
   REQUIRE(I64Ctz);
   struct {
     int64_t expected;
@@ -1017,7 +997,7 @@
   }
 }
 
-TEST(Run_Wasm_I64Popcnt) {
+WASM_EXEC_TEST(I64Popcnt2) {
   REQUIRE(I64Popcnt);
   struct {
     int64_t expected;
@@ -1088,7 +1068,7 @@
 }
 }
 
-TEST(Run_WasmCall_Int64Sub) {
+WASM_EXEC_TEST(Call_Int64Sub) {
   REQUIRE(I64Sub);
   // Build the target function.
   TestSignatures sigs;
@@ -1099,7 +1079,7 @@
 
   // Build the caller function.
   WasmRunner<int64_t> r(&module, MachineType::Int64(), MachineType::Int64());
-  BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  BUILD(r, WASM_CALL_FUNCTION2(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_INT32_INPUTS(i) {
     FOR_INT32_INPUTS(j) {
@@ -1115,7 +1095,7 @@
   }
 }
 
-TEST(Run_Wasm_LoadStoreI64_sx) {
+WASM_EXEC_TEST(LoadStoreI64_sx) {
   REQUIRE(I64LoadStore);
   REQUIRE(DepthFirst);
   byte loads[] = {kExprI64LoadMem8S, kExprI64LoadMem16S, kExprI64LoadMem32S,
@@ -1126,12 +1106,16 @@
     byte* memory = module.AddMemoryElems<byte>(16);
     WasmRunner<int64_t> r(&module);
 
-    byte code[] = {kExprI64StoreMem, ZERO_ALIGNMENT,
-                   ZERO_OFFSET,          // --
-                   kExprI8Const,     8,  // --
-                   loads[m],         ZERO_ALIGNMENT,
-                   ZERO_OFFSET,           // --
-                   kExprI8Const,     0};  // --
+    byte code[] = {
+        kExprI8Const,     8,  // --
+        kExprI8Const,     0,  // --
+        loads[m],             // --
+        ZERO_ALIGNMENT,       // --
+        ZERO_OFFSET,          // --
+        kExprI64StoreMem,     // --
+        ZERO_ALIGNMENT,       // --
+        ZERO_OFFSET           // --
+    };
 
     r.Build(code, code + arraysize(code));
 
@@ -1152,7 +1136,7 @@
   }
 }
 
-TEST(Run_Wasm_I64SConvertF32b) {
+WASM_EXEC_TEST(I64SConvertF32b) {
   REQUIRE(I64SConvertF32);
   WasmRunner<int64_t> r(MachineType::Float32());
   BUILD(r, WASM_I64_SCONVERT_F32(WASM_GET_LOCAL(0)));
@@ -1167,7 +1151,7 @@
   }
 }
 
-TEST(Run_Wasm_I64SConvertF64b) {
+WASM_EXEC_TEST(I64SConvertF64b) {
   REQUIRE(I64SConvertF64);
   WasmRunner<int64_t> r(MachineType::Float64());
   BUILD(r, WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(0)));
@@ -1182,7 +1166,7 @@
   }
 }
 
-TEST(Run_Wasm_I64UConvertF32b) {
+WASM_EXEC_TEST(I64UConvertF32b) {
   REQUIRE(I64UConvertF32);
   WasmRunner<uint64_t> r(MachineType::Float32());
   BUILD(r, WASM_I64_UCONVERT_F32(WASM_GET_LOCAL(0)));
@@ -1196,7 +1180,7 @@
   }
 }
 
-TEST(Run_Wasm_I64UConvertF64b) {
+WASM_EXEC_TEST(I64UConvertF64b) {
   REQUIRE(I64UConvertF64);
   WasmRunner<uint64_t> r(MachineType::Float64());
   BUILD(r, WASM_I64_UCONVERT_F64(WASM_GET_LOCAL(0)));
@@ -1210,7 +1194,7 @@
   }
 }
 
-TEST(Run_Wasm_I64ReinterpretF64) {
+WASM_EXEC_TEST(I64ReinterpretF64) {
   REQUIRE(I64ReinterpretF64);
   TestingModule module;
   int64_t* memory = module.AddMemoryElems<int64_t>(8);
@@ -1226,7 +1210,7 @@
   }
 }
 
-TEST(Run_Wasm_F64ReinterpretI64) {
+WASM_EXEC_TEST(F64ReinterpretI64) {
   REQUIRE(F64ReinterpretI64);
   TestingModule module;
   int64_t* memory = module.AddMemoryElems<int64_t>(8);
@@ -1244,7 +1228,7 @@
   }
 }
 
-TEST(Run_Wasm_LoadMemI64) {
+WASM_EXEC_TEST(LoadMemI64) {
   REQUIRE(I64LoadStore);
   TestingModule module;
   int64_t* memory = module.AddMemoryElems<int64_t>(8);
@@ -1263,7 +1247,7 @@
   CHECK_EQ(77777777, r.Call());
 }
 
-TEST(Run_Wasm_MemI64_Sum) {
+WASM_EXEC_TEST(MemI64_Sum) {
   REQUIRE(I64LoadStore);
   REQUIRE(I64Add);
   REQUIRE(I64Sub);
@@ -1299,7 +1283,7 @@
   }
 }
 
-TEST(Run_Wasm_I64Global) {
+WASM_EXEC_TEST(I64Global) {
   REQUIRE(I64LoadStore);
   REQUIRE(I64SConvertI32);
   REQUIRE(I64And);
@@ -1321,7 +1305,7 @@
   }
 }
 
-TEST(Run_Wasm_I64Eqz) {
+WASM_EXEC_TEST(I64Eqz) {
   REQUIRE(I64Eq);
 
   WasmRunner<int32_t> r(MachineType::Int64());
@@ -1333,7 +1317,7 @@
   }
 }
 
-TEST(Run_Wasm_I64Ror) {
+WASM_EXEC_TEST(I64Ror) {
   REQUIRE(I64Ror);
   WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_ROR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -1346,7 +1330,7 @@
   }
 }
 
-TEST(Run_Wasm_I64Rol) {
+WASM_EXEC_TEST(I64Rol) {
   REQUIRE(I64Rol);
   WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_ROL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
diff --git a/test/cctest/wasm/test-run-wasm-asmjs.cc b/test/cctest/wasm/test-run-wasm-asmjs.cc
new file mode 100644
index 0000000..c597fc8
--- /dev/null
+++ b/test/cctest/wasm/test-run-wasm-asmjs.cc
@@ -0,0 +1,195 @@
+// 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 <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "src/base/platform/elapsed-timer.h"
+
+#include "src/wasm/wasm-macro-gen.h"
+
+#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/value-helper.h"
+#include "test/cctest/wasm/test-signatures.h"
+#include "test/cctest/wasm/wasm-run-utils.h"
+
+using namespace v8::base;
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+using namespace v8::internal::wasm;
+
+// for even shorter tests.
+#define B2(a, b) kExprBlock, a, b, kExprEnd
+#define B1(a) kExprBlock, a, kExprEnd
+#define RET(x) x, kExprReturn, 1
+#define RET_I8(x) kExprI8Const, x, kExprReturn, 1
+
+WASM_EXEC_TEST(Int32AsmjsDivS) {
+  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+  BUILD(r, WASM_BINOP(kExprI32AsmjsDivS, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  const int32_t kMin = std::numeric_limits<int32_t>::min();
+  CHECK_EQ(0, r.Call(0, 100));
+  CHECK_EQ(0, r.Call(100, 0));
+  CHECK_EQ(0, r.Call(-1001, 0));
+  CHECK_EQ(kMin, r.Call(kMin, -1));
+  CHECK_EQ(0, r.Call(kMin, 0));
+}
+
+WASM_EXEC_TEST(Int32AsmjsRemS) {
+  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+  BUILD(r, WASM_BINOP(kExprI32AsmjsRemS, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  const int32_t kMin = std::numeric_limits<int32_t>::min();
+  CHECK_EQ(33, r.Call(133, 100));
+  CHECK_EQ(0, r.Call(kMin, -1));
+  CHECK_EQ(0, r.Call(100, 0));
+  CHECK_EQ(0, r.Call(-1001, 0));
+  CHECK_EQ(0, r.Call(kMin, 0));
+}
+
+WASM_EXEC_TEST(Int32AsmjsDivU) {
+  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+  BUILD(r, WASM_BINOP(kExprI32AsmjsDivU, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  const int32_t kMin = std::numeric_limits<int32_t>::min();
+  CHECK_EQ(0, r.Call(0, 100));
+  CHECK_EQ(0, r.Call(kMin, -1));
+  CHECK_EQ(0, r.Call(100, 0));
+  CHECK_EQ(0, r.Call(-1001, 0));
+  CHECK_EQ(0, r.Call(kMin, 0));
+}
+
+WASM_EXEC_TEST(Int32AsmjsRemU) {
+  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+  BUILD(r, WASM_BINOP(kExprI32AsmjsRemU, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  const int32_t kMin = std::numeric_limits<int32_t>::min();
+  CHECK_EQ(17, r.Call(217, 100));
+  CHECK_EQ(0, r.Call(100, 0));
+  CHECK_EQ(0, r.Call(-1001, 0));
+  CHECK_EQ(0, r.Call(kMin, 0));
+  CHECK_EQ(kMin, r.Call(kMin, -1));
+}
+
+WASM_EXEC_TEST(I32AsmjsSConvertF32) {
+  WasmRunner<int32_t> r(MachineType::Float32());
+  BUILD(r, WASM_UNOP(kExprI32AsmjsSConvertF32, WASM_GET_LOCAL(0)));
+
+  FOR_FLOAT32_INPUTS(i) {
+    int32_t expected = DoubleToInt32(*i);
+    CHECK_EQ(expected, r.Call(*i));
+  }
+}
+
+WASM_EXEC_TEST(I32AsmjsSConvertF64) {
+  WasmRunner<int32_t> r(MachineType::Float64());
+  BUILD(r, WASM_UNOP(kExprI32AsmjsSConvertF64, WASM_GET_LOCAL(0)));
+
+  FOR_FLOAT64_INPUTS(i) {
+    int32_t expected = DoubleToInt32(*i);
+    CHECK_EQ(expected, r.Call(*i));
+  }
+}
+
+WASM_EXEC_TEST(I32AsmjsUConvertF32) {
+  WasmRunner<uint32_t> r(MachineType::Float32());
+  BUILD(r, WASM_UNOP(kExprI32AsmjsUConvertF32, WASM_GET_LOCAL(0)));
+
+  FOR_FLOAT32_INPUTS(i) {
+    uint32_t expected = DoubleToUint32(*i);
+    CHECK_EQ(expected, r.Call(*i));
+  }
+}
+
+WASM_EXEC_TEST(I32AsmjsUConvertF64) {
+  WasmRunner<uint32_t> r(MachineType::Float64());
+  BUILD(r, WASM_UNOP(kExprI32AsmjsUConvertF64, WASM_GET_LOCAL(0)));
+
+  FOR_FLOAT64_INPUTS(i) {
+    uint32_t expected = DoubleToUint32(*i);
+    CHECK_EQ(expected, r.Call(*i));
+  }
+}
+
+WASM_EXEC_TEST(LoadMemI32_oob_asm) {
+  TestingModule module;
+  int32_t* memory = module.AddMemoryElems<int32_t>(8);
+  WasmRunner<int32_t> r(&module, MachineType::Uint32());
+  module.RandomizeMemory(1112);
+
+  BUILD(r, WASM_UNOP(kExprI32AsmjsLoadMem, WASM_GET_LOCAL(0)));
+
+  memory[0] = 999999;
+  CHECK_EQ(999999, r.Call(0u));
+  // TODO(titzer): offset 29-31 should also be OOB.
+  for (uint32_t offset = 32; offset < 40; offset++) {
+    CHECK_EQ(0, r.Call(offset));
+  }
+
+  for (uint32_t offset = 0x80000000; offset < 0x80000010; offset++) {
+    CHECK_EQ(0, r.Call(offset));
+  }
+}
+
+WASM_EXEC_TEST(LoadMemF32_oob_asm) {
+  TestingModule module;
+  float* memory = module.AddMemoryElems<float>(8);
+  WasmRunner<float> r(&module, MachineType::Uint32());
+  module.RandomizeMemory(1112);
+
+  BUILD(r, WASM_UNOP(kExprF32AsmjsLoadMem, WASM_GET_LOCAL(0)));
+
+  memory[0] = 9999.5f;
+  CHECK_EQ(9999.5f, r.Call(0u));
+  // TODO(titzer): offset 29-31 should also be OOB.
+  for (uint32_t offset = 32; offset < 40; offset++) {
+    CHECK(std::isnan(r.Call(offset)));
+  }
+
+  for (uint32_t offset = 0x80000000; offset < 0x80000010; offset++) {
+    CHECK(std::isnan(r.Call(offset)));
+  }
+}
+
+WASM_EXEC_TEST(LoadMemF64_oob_asm) {
+  TestingModule module;
+  double* memory = module.AddMemoryElems<double>(8);
+  WasmRunner<double> r(&module, MachineType::Uint32());
+  module.RandomizeMemory(1112);
+
+  BUILD(r, WASM_UNOP(kExprF64AsmjsLoadMem, WASM_GET_LOCAL(0)));
+
+  memory[0] = 9799.5;
+  CHECK_EQ(9799.5, r.Call(0u));
+  memory[1] = 11799.25;
+  CHECK_EQ(11799.25, r.Call(8u));
+  // TODO(titzer): offset 57-63 should also be OOB.
+  for (uint32_t offset = 64; offset < 80; offset++) {
+    CHECK(std::isnan(r.Call(offset)));
+  }
+
+  for (uint32_t offset = 0x80000000; offset < 0x80000010; offset++) {
+    CHECK(std::isnan(r.Call(offset)));
+  }
+}
+
+WASM_EXEC_TEST(StoreMemI32_oob_asm) {
+  TestingModule module;
+  int32_t* memory = module.AddMemoryElems<int32_t>(8);
+  WasmRunner<int32_t> r(&module, MachineType::Uint32(), MachineType::Uint32());
+  module.RandomizeMemory(1112);
+
+  BUILD(r, WASM_BINOP(kExprI32AsmjsStoreMem, WASM_GET_LOCAL(0),
+                      WASM_GET_LOCAL(1)));
+
+  memory[0] = 7777;
+  CHECK_EQ(999999, r.Call(0u, 999999));
+  CHECK_EQ(999999, memory[0]);
+  // TODO(titzer): offset 29-31 should also be OOB.
+  for (uint32_t offset = 32; offset < 40; offset++) {
+    CHECK_EQ(8888, r.Call(offset, 8888));
+  }
+
+  for (uint32_t offset = 0x10000000; offset < 0xF0000000; offset += 0x1000000) {
+    CHECK_EQ(7777, r.Call(offset, 7777));
+  }
+}
diff --git a/test/cctest/wasm/test-run-wasm-js.cc b/test/cctest/wasm/test-run-wasm-js.cc
index 6d95d6e..827cb3a 100644
--- a/test/cctest/wasm/test-run-wasm-js.cc
+++ b/test/cctest/wasm/test-run-wasm-js.cc
@@ -25,14 +25,12 @@
     r.Build(code, code + arraysize(code)); \
   } while (false)
 
-
 #define ADD_CODE(vec, ...)                                              \
   do {                                                                  \
     byte __buf[] = {__VA_ARGS__};                                       \
     for (size_t i = 0; i < sizeof(__buf); i++) vec.push_back(__buf[i]); \
   } while (false)
 
-
 namespace {
 // A helper for generating predictable but unique argument values that
 // are easy to debug (e.g. with misaligned stacks).
@@ -48,23 +46,6 @@
   }
 };
 
-
-uint32_t AddJsFunction(TestingModule* module, FunctionSig* sig,
-                       const char* source) {
-  Handle<JSFunction> jsfunc = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
-      *v8::Local<v8::Function>::Cast(CompileRun(source))));
-  module->AddFunction(sig, Handle<Code>::null());
-  uint32_t index = static_cast<uint32_t>(module->module->functions.size() - 1);
-  Isolate* isolate = CcTest::InitIsolateOnce();
-  WasmName module_name = {"test", 4};
-  WasmName function_name = {nullptr, 0};
-  Handle<Code> code = CompileWasmToJSWrapper(isolate, module, jsfunc, sig,
-                                             module_name, function_name);
-  module->instance->function_code[index] = code;
-  return index;
-}
-
-
 uint32_t AddJSSelector(TestingModule* module, FunctionSig* sig, int which) {
   const int kMaxParams = 11;
   static const char* formals[kMaxParams] = {"",
@@ -86,22 +67,9 @@
   SNPrintF(source, "(function(%s) { return %c; })",
            formals[sig->parameter_count()], param);
 
-  return AddJsFunction(module, sig, source.start());
+  return module->AddJsFunction(sig, source.start());
 }
 
-
-Handle<JSFunction> WrapCode(ModuleEnv* module, uint32_t index) {
-  Isolate* isolate = module->module->shared_isolate;
-  // Wrap the code so it can be called as a JS function.
-  Handle<String> name = isolate->factory()->NewStringFromStaticChars("main");
-  Handle<JSObject> module_object = Handle<JSObject>(0, isolate);
-  Handle<Code> code = module->instance->function_code[index];
-  WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
-  return compiler::CompileJSToWasmWrapper(isolate, module, name, code,
-                                          module_object, index);
-}
-
-
 void EXPECT_CALL(double expected, Handle<JSFunction> jsfunc,
                  Handle<Object>* buffer, int count) {
   Isolate* isolate = jsfunc->GetIsolate();
@@ -119,7 +87,6 @@
   }
 }
 
-
 void EXPECT_CALL(double expected, Handle<JSFunction> jsfunc, double a,
                  double b) {
   Isolate* isolate = jsfunc->GetIsolate();
@@ -134,68 +101,61 @@
   TestingModule module;
   WasmFunctionCompiler t(sigs.i_ii(), &module);
   BUILD(t, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+  Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
 
   EXPECT_CALL(33, jsfunc, 44, 11);
   EXPECT_CALL(-8723487, jsfunc, -8000000, 723487);
 }
 
-
 TEST(Run_Float32Div_jswrapped) {
   TestSignatures sigs;
   TestingModule module;
   WasmFunctionCompiler t(sigs.f_ff(), &module);
   BUILD(t, WASM_F32_DIV(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+  Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
 
   EXPECT_CALL(92, jsfunc, 46, 0.5);
   EXPECT_CALL(64, jsfunc, -16, -0.25);
 }
 
-
 TEST(Run_Float64Add_jswrapped) {
   TestSignatures sigs;
   TestingModule module;
   WasmFunctionCompiler t(sigs.d_dd(), &module);
   BUILD(t, WASM_F64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+  Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
 
   EXPECT_CALL(3, jsfunc, 2, 1);
   EXPECT_CALL(-5.5, jsfunc, -5.25, -0.25);
 }
 
-
 TEST(Run_I32Popcount_jswrapped) {
   TestSignatures sigs;
   TestingModule module;
   WasmFunctionCompiler t(sigs.i_i(), &module);
   BUILD(t, WASM_I32_POPCNT(WASM_GET_LOCAL(0)));
-  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+  Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
 
   EXPECT_CALL(2, jsfunc, 9, 0);
   EXPECT_CALL(3, jsfunc, 11, 0);
   EXPECT_CALL(6, jsfunc, 0x3F, 0);
-
-  USE(AddJsFunction);
 }
 
-
 TEST(Run_CallJS_Add_jswrapped) {
   TestSignatures sigs;
   TestingModule module;
   WasmFunctionCompiler t(sigs.i_i(), &module);
   uint32_t js_index =
-      AddJsFunction(&module, sigs.i_i(), "(function(a) { return a + 99; })");
-  BUILD(t, WASM_CALL_FUNCTION(js_index, WASM_GET_LOCAL(0)));
+      module.AddJsFunction(sigs.i_i(), "(function(a) { return a + 99; })");
+  BUILD(t, WASM_CALL_FUNCTION1(js_index, WASM_GET_LOCAL(0)));
 
-  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+  Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
 
   EXPECT_CALL(101, jsfunc, 2, -8);
   EXPECT_CALL(199, jsfunc, 100, -1);
   EXPECT_CALL(-666666801, jsfunc, -666666900, -1);
 }
 
-
 void RunJSSelectTest(int which) {
   const int kMaxParams = 8;
   PredictableInputValues inputs(0x100);
@@ -212,24 +172,25 @@
 
     {
       std::vector<byte> code;
-      ADD_CODE(code, kExprCallFunction, static_cast<byte>(js_index));
 
       for (int i = 0; i < num_params; i++) {
         ADD_CODE(code, WASM_F64(inputs.arg_d(i)));
       }
 
+      ADD_CODE(code, kExprCallFunction, static_cast<byte>(num_params),
+               static_cast<byte>(js_index));
+
       size_t end = code.size();
       code.push_back(0);
       t.Build(&code[0], &code[end]);
     }
 
-    Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+    Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
     double expected = inputs.arg_d(which);
     EXPECT_CALL(expected, jsfunc, 0.0, 0.0);
   }
 }
 
-
 TEST(Run_JSSelect_0) { RunJSSelectTest(0); }
 
 TEST(Run_JSSelect_1) { RunJSSelectTest(1); }
@@ -246,7 +207,6 @@
 
 TEST(Run_JSSelect_7) { RunJSSelectTest(7); }
 
-
 void RunWASMSelectTest(int which) {
   PredictableInputValues inputs(0x200);
   Isolate* isolate = CcTest::InitIsolateOnce();
@@ -260,7 +220,7 @@
     TestingModule module;
     WasmFunctionCompiler t(&sig, &module);
     BUILD(t, WASM_GET_LOCAL(which));
-    Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+    Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
 
     Handle<Object> args[] = {
         isolate->factory()->NewNumber(inputs.arg_d(0)),
@@ -278,7 +238,6 @@
   }
 }
 
-
 TEST(Run_WASMSelect_0) { RunWASMSelectTest(0); }
 
 TEST(Run_WASMSelect_1) { RunWASMSelectTest(1); }
@@ -295,7 +254,6 @@
 
 TEST(Run_WASMSelect_7) { RunWASMSelectTest(7); }
 
-
 void RunWASMSelectAlignTest(int num_args, int num_params) {
   PredictableInputValues inputs(0x300);
   Isolate* isolate = CcTest::InitIsolateOnce();
@@ -310,7 +268,7 @@
     TestingModule module;
     WasmFunctionCompiler t(&sig, &module);
     BUILD(t, WASM_GET_LOCAL(which));
-    Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+    Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
 
     Handle<Object> args[] = {isolate->factory()->NewNumber(inputs.arg_d(0)),
                              isolate->factory()->NewNumber(inputs.arg_d(1)),
@@ -329,31 +287,26 @@
   }
 }
 
-
 TEST(Run_WASMSelectAlign_0) {
   RunWASMSelectAlignTest(0, 1);
   RunWASMSelectAlignTest(0, 2);
 }
 
-
 TEST(Run_WASMSelectAlign_1) {
   RunWASMSelectAlignTest(1, 2);
   RunWASMSelectAlignTest(1, 3);
 }
 
-
 TEST(Run_WASMSelectAlign_2) {
   RunWASMSelectAlignTest(2, 3);
   RunWASMSelectAlignTest(2, 4);
 }
 
-
 TEST(Run_WASMSelectAlign_3) {
   RunWASMSelectAlignTest(3, 3);
   RunWASMSelectAlignTest(3, 4);
 }
 
-
 TEST(Run_WASMSelectAlign_4) {
   RunWASMSelectAlignTest(4, 3);
   RunWASMSelectAlignTest(4, 4);
@@ -400,12 +353,13 @@
 
   // Build the calling code.
   std::vector<byte> code;
-  ADD_CODE(code, kExprCallFunction, 0);
 
   for (int i = 0; i < num_params; i++) {
     ADD_CODE(code, WASM_GET_LOCAL(i));
   }
 
+  ADD_CODE(code, kExprCallFunction, static_cast<byte>(num_params), 0);
+
   size_t end = code.size();
   code.push_back(0);
 
@@ -418,7 +372,7 @@
     WasmFunctionCompiler t(&sig, &module);
     t.Build(&code[0], &code[end]);
 
-    Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+    Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
 
     Handle<Object> args[] = {
         factory->NewNumber(inputs.arg_d(0)),
@@ -439,7 +393,6 @@
   }
 }
 
-
 TEST(Run_JSSelectAlign_0) {
   RunJSSelectAlignTest(0, 1);
   RunJSSelectAlignTest(0, 2);
diff --git a/test/cctest/wasm/test-run-wasm-module.cc b/test/cctest/wasm/test-run-wasm-module.cc
index 118a91f..05edd62 100644
--- a/test/cctest/wasm/test-run-wasm-module.cc
+++ b/test/cctest/wasm/test-run-wasm-module.cc
@@ -12,14 +12,13 @@
 #include "src/wasm/wasm-opcodes.h"
 
 #include "test/cctest/cctest.h"
+#include "test/cctest/wasm/test-signatures.h"
 
 using namespace v8::base;
 using namespace v8::internal;
 using namespace v8::internal::compiler;
 using namespace v8::internal::wasm;
 
-
-// TODO(titzer): fix arm64 frame alignment.
 namespace {
 void TestModule(WasmModuleIndex* module, int32_t expected_result) {
   Isolate* isolate = CcTest::InitIsolateOnce();
@@ -31,50 +30,16 @@
 }
 }  // namespace
 
-
-// A raw test that skips the WasmModuleBuilder.
-TEST(Run_WasmModule_CallAdd_rev) {
-  static const byte data[] = {
-      WASM_MODULE_HEADER,
-      // sig#0 ------------------------------------------
-      WASM_SECTION_SIGNATURES_SIZE + 7,          // Section size.
-      WASM_SECTION_SIGNATURES, 2, 0, kLocalI32,  // void -> int
-      2, kLocalI32, kLocalI32, kLocalI32,        // int,int -> int
-      // func#0 (main) ----------------------------------
-      WASM_SECTION_FUNCTIONS_SIZE + 24, WASM_SECTION_FUNCTIONS, 2,
-      kDeclFunctionExport, 0, 0,  // sig index
-      7, 0,                       // body size
-      0,                          // locals
-      kExprCallFunction, 1,       // --
-      kExprI8Const, 77,           // --
-      kExprI8Const, 22,           // --
-      // func#1 -----------------------------------------
-      0,                 // no name, not exported
-      1, 0,              // sig index
-      6, 0,              // body size
-      0,                 // locals
-      kExprI32Add,       // --
-      kExprGetLocal, 0,  // --
-      kExprGetLocal, 1,  // --
-  };
-
-  Isolate* isolate = CcTest::InitIsolateOnce();
-  HandleScope scope(isolate);
-  WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
-  int32_t result =
-      CompileAndRunWasmModule(isolate, data, data + arraysize(data));
-  CHECK_EQ(99, result);
-}
-
-
 TEST(Run_WasmModule_Return114) {
   static const int32_t kReturnValue = 114;
+  TestSignatures sigs;
   v8::base::AccountingAllocator allocator;
   Zone zone(&allocator);
+
   WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
   uint16_t f_index = builder->AddFunction();
   WasmFunctionBuilder* f = builder->FunctionAt(f_index);
-  f->ReturnType(kAstI32);
+  f->SetSignature(sigs.i_v());
   f->Exported(1);
   byte code[] = {WASM_I8(kReturnValue)};
   f->EmitCode(code, sizeof(code));
@@ -82,38 +47,43 @@
   TestModule(writer->WriteTo(&zone), kReturnValue);
 }
 
-
 TEST(Run_WasmModule_CallAdd) {
   v8::base::AccountingAllocator allocator;
   Zone zone(&allocator);
+  TestSignatures sigs;
+
   WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
+
   uint16_t f1_index = builder->AddFunction();
   WasmFunctionBuilder* f = builder->FunctionAt(f1_index);
-  f->ReturnType(kAstI32);
-  uint16_t param1 = f->AddParam(kAstI32);
-  uint16_t param2 = f->AddParam(kAstI32);
+  f->SetSignature(sigs.i_ii());
+  uint16_t param1 = 0;
+  uint16_t param2 = 1;
   byte code1[] = {WASM_I32_ADD(WASM_GET_LOCAL(param1), WASM_GET_LOCAL(param2))};
-  uint32_t local_indices1[] = {2, 4};
-  f->EmitCode(code1, sizeof(code1), local_indices1, sizeof(local_indices1) / 4);
+  f->EmitCode(code1, sizeof(code1));
+
   uint16_t f2_index = builder->AddFunction();
   f = builder->FunctionAt(f2_index);
-  f->ReturnType(kAstI32);
+  f->SetSignature(sigs.i_v());
+
   f->Exported(1);
-  byte code2[] = {WASM_CALL_FUNCTION(f1_index, WASM_I8(77), WASM_I8(22))};
+  byte code2[] = {WASM_CALL_FUNCTION2(f1_index, WASM_I8(77), WASM_I8(22))};
   f->EmitCode(code2, sizeof(code2));
   WasmModuleWriter* writer = builder->Build(&zone);
   TestModule(writer->WriteTo(&zone), 99);
 }
 
-
 TEST(Run_WasmModule_ReadLoadedDataSegment) {
   static const byte kDataSegmentDest0 = 12;
   v8::base::AccountingAllocator allocator;
   Zone zone(&allocator);
+  TestSignatures sigs;
+
   WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
   uint16_t f_index = builder->AddFunction();
   WasmFunctionBuilder* f = builder->FunctionAt(f_index);
-  f->ReturnType(kAstI32);
+  f->SetSignature(sigs.i_v());
+
   f->Exported(1);
   byte code[] = {
       WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(kDataSegmentDest0))};
@@ -129,10 +99,13 @@
   static const int kCheckSize = 16 * 1024;
   v8::base::AccountingAllocator allocator;
   Zone zone(&allocator);
+  TestSignatures sigs;
+
   WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
   uint16_t f_index = builder->AddFunction();
   WasmFunctionBuilder* f = builder->FunctionAt(f_index);
-  f->ReturnType(kAstI32);
+  f->SetSignature(sigs.i_v());
+
   uint16_t localIndex = f->AddLocal(kAstI32);
   f->Exported(1);
   byte code[] = {WASM_BLOCK(
@@ -143,7 +116,7 @@
               WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(localIndex)),
               WASM_BRV(2, WASM_I8(-1)), WASM_INC_LOCAL_BY(localIndex, 4))),
       WASM_I8(11))};
-  f->EmitCode(code, sizeof(code), nullptr, 0);
+  f->EmitCode(code, sizeof(code));
   WasmModuleWriter* writer = builder->Build(&zone);
   TestModule(writer->WriteTo(&zone), 11);
 }
@@ -151,10 +124,13 @@
 TEST(Run_WasmModule_CallMain_recursive) {
   v8::base::AccountingAllocator allocator;
   Zone zone(&allocator);
+  TestSignatures sigs;
+
   WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
   uint16_t f_index = builder->AddFunction();
   WasmFunctionBuilder* f = builder->FunctionAt(f_index);
-  f->ReturnType(kAstI32);
+  f->SetSignature(sigs.i_v());
+
   uint16_t localIndex = f->AddLocal(kAstI32);
   f->Exported(1);
   byte code[] = {WASM_BLOCK(
@@ -165,7 +141,7 @@
                                                 WASM_INC_LOCAL(localIndex)),
                               WASM_BRV(1, WASM_CALL_FUNCTION0(0))),
                    WASM_BRV(0, WASM_I8(55))))};
-  f->EmitCode(code, sizeof(code), nullptr, 0);
+  f->EmitCode(code, sizeof(code));
   WasmModuleWriter* writer = builder->Build(&zone);
   TestModule(writer->WriteTo(&zone), 55);
 }
@@ -173,22 +149,24 @@
 TEST(Run_WasmModule_Global) {
   v8::base::AccountingAllocator allocator;
   Zone zone(&allocator);
+  TestSignatures sigs;
+
   WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
   uint32_t global1 = builder->AddGlobal(MachineType::Int32(), 0);
   uint32_t global2 = builder->AddGlobal(MachineType::Int32(), 0);
   uint16_t f1_index = builder->AddFunction();
   WasmFunctionBuilder* f = builder->FunctionAt(f1_index);
-  f->ReturnType(kAstI32);
+  f->SetSignature(sigs.i_v());
   byte code1[] = {
       WASM_I32_ADD(WASM_LOAD_GLOBAL(global1), WASM_LOAD_GLOBAL(global2))};
   f->EmitCode(code1, sizeof(code1));
   uint16_t f2_index = builder->AddFunction();
   f = builder->FunctionAt(f2_index);
-  f->ReturnType(kAstI32);
+  f->SetSignature(sigs.i_v());
   f->Exported(1);
   byte code2[] = {WASM_STORE_GLOBAL(global1, WASM_I32V_1(56)),
                   WASM_STORE_GLOBAL(global2, WASM_I32V_1(41)),
-                  WASM_RETURN(WASM_CALL_FUNCTION0(f1_index))};
+                  WASM_RETURN1(WASM_CALL_FUNCTION0(f1_index))};
   f->EmitCode(code2, sizeof(code2));
   WasmModuleWriter* writer = builder->Build(&zone);
   TestModule(writer->WriteTo(&zone), 97);
diff --git a/test/cctest/wasm/test-run-wasm.cc b/test/cctest/wasm/test-run-wasm.cc
index 70d461b..236624f 100644
--- a/test/cctest/wasm/test-run-wasm.cc
+++ b/test/cctest/wasm/test-run-wasm.cc
@@ -6,6 +6,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "src/base/platform/elapsed-timer.h"
+
 #include "src/wasm/wasm-macro-gen.h"
 
 #include "test/cctest/cctest.h"
@@ -19,12 +21,12 @@
 using namespace v8::internal::wasm;
 
 // for even shorter tests.
-#define B2(a, b) kExprBlock, 2, a, b
-#define B1(a) kExprBlock, 1, a
-#define RET(x) kExprReturn, x
-#define RET_I8(x) kExprReturn, kExprI8Const, x
+#define B2(a, b) kExprBlock, a, b, kExprEnd
+#define B1(a) kExprBlock, a, kExprEnd
+#define RET(x) x, kExprReturn, 1
+#define RET_I8(x) kExprI8Const, x, kExprReturn, 1
 
-TEST(Run_WasmInt8Const) {
+WASM_EXEC_TEST(Int8Const) {
   WasmRunner<int32_t> r;
   const byte kExpectedValue = 121;
   // return(kExpectedValue)
@@ -32,8 +34,7 @@
   CHECK_EQ(kExpectedValue, r.Call());
 }
 
-
-TEST(Run_WasmInt8Const_fallthru1) {
+WASM_EXEC_TEST(Int8Const_fallthru1) {
   WasmRunner<int32_t> r;
   const byte kExpectedValue = 122;
   // kExpectedValue
@@ -41,8 +42,7 @@
   CHECK_EQ(kExpectedValue, r.Call());
 }
 
-
-TEST(Run_WasmInt8Const_fallthru2) {
+WASM_EXEC_TEST(Int8Const_fallthru2) {
   WasmRunner<int32_t> r;
   const byte kExpectedValue = 123;
   // -99 kExpectedValue
@@ -50,8 +50,7 @@
   CHECK_EQ(kExpectedValue, r.Call());
 }
 
-
-TEST(Run_WasmInt8Const_all) {
+WASM_EXEC_TEST(Int8Const_all) {
   for (int value = -128; value <= 127; value++) {
     WasmRunner<int32_t> r;
     // return(value)
@@ -61,8 +60,7 @@
   }
 }
 
-
-TEST(Run_WasmInt32Const) {
+WASM_EXEC_TEST(Int32Const) {
   WasmRunner<int32_t> r;
   const int32_t kExpectedValue = 0x11223344;
   // return(kExpectedValue)
@@ -70,8 +68,7 @@
   CHECK_EQ(kExpectedValue, r.Call());
 }
 
-
-TEST(Run_WasmInt32Const_many) {
+WASM_EXEC_TEST(Int32Const_many) {
   FOR_INT32_INPUTS(i) {
     WasmRunner<int32_t> r;
     const int32_t kExpectedValue = *i;
@@ -81,8 +78,7 @@
   }
 }
 
-
-TEST(Run_WasmMemorySize) {
+WASM_EXEC_TEST(MemorySize) {
   TestingModule module;
   WasmRunner<int32_t> r(&module);
   module.AddMemory(1024);
@@ -90,56 +86,49 @@
   CHECK_EQ(1024, r.Call());
 }
 
-
-TEST(Run_WasmInt32Param0) {
+WASM_EXEC_TEST(Int32Param0) {
   WasmRunner<int32_t> r(MachineType::Int32());
   // return(local[0])
   BUILD(r, WASM_GET_LOCAL(0));
   FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
 }
 
-
-TEST(Run_WasmInt32Param0_fallthru) {
+WASM_EXEC_TEST(Int32Param0_fallthru) {
   WasmRunner<int32_t> r(MachineType::Int32());
   // local[0]
   BUILD(r, WASM_GET_LOCAL(0));
   FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
 }
 
-
-TEST(Run_WasmInt32Param1) {
+WASM_EXEC_TEST(Int32Param1) {
   WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
   // local[1]
   BUILD(r, WASM_GET_LOCAL(1));
   FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(-111, *i)); }
 }
 
-
-TEST(Run_WasmInt32Add) {
+WASM_EXEC_TEST(Int32Add) {
   WasmRunner<int32_t> r;
   // 11 + 44
   BUILD(r, WASM_I32_ADD(WASM_I8(11), WASM_I8(44)));
   CHECK_EQ(55, r.Call());
 }
 
-
-TEST(Run_WasmInt32Add_P) {
+WASM_EXEC_TEST(Int32Add_P) {
   WasmRunner<int32_t> r(MachineType::Int32());
   // p0 + 13
   BUILD(r, WASM_I32_ADD(WASM_I8(13), WASM_GET_LOCAL(0)));
   FOR_INT32_INPUTS(i) { CHECK_EQ(*i + 13, r.Call(*i)); }
 }
 
-
-TEST(Run_WasmInt32Add_P_fallthru) {
+WASM_EXEC_TEST(Int32Add_P_fallthru) {
   WasmRunner<int32_t> r(MachineType::Int32());
   // p0 + 13
   BUILD(r, WASM_I32_ADD(WASM_I8(13), WASM_GET_LOCAL(0)));
   FOR_INT32_INPUTS(i) { CHECK_EQ(*i + 13, r.Call(*i)); }
 }
 
-
-TEST(Run_WasmInt32Add_P2) {
+WASM_EXEC_TEST(Int32Add_P2) {
   WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
   //  p0 + p1
   BUILD(r, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -152,8 +141,7 @@
   }
 }
 
-
-TEST(Run_WasmFloat32Add) {
+WASM_EXEC_TEST(Float32Add) {
   WasmRunner<int32_t> r;
   // int(11.5f + 44.5f)
   BUILD(r,
@@ -161,15 +149,13 @@
   CHECK_EQ(56, r.Call());
 }
 
-
-TEST(Run_WasmFloat64Add) {
+WASM_EXEC_TEST(Float64Add) {
   WasmRunner<int32_t> r;
   // return int(13.5d + 43.5d)
   BUILD(r, WASM_I32_SCONVERT_F64(WASM_F64_ADD(WASM_F64(13.5), WASM_F64(43.5))));
   CHECK_EQ(57, r.Call());
 }
 
-
 void TestInt32Binop(WasmOpcode opcode, int32_t expected, int32_t a, int32_t b) {
   {
     WasmRunner<int32_t> r;
@@ -185,7 +171,7 @@
   }
 }
 
-TEST(Run_WasmInt32Binops) {
+WASM_EXEC_TEST(Int32Binops) {
   TestInt32Binop(kExprI32Add, 88888888, 33333333, 55555555);
   TestInt32Binop(kExprI32Sub, -1111111, 7777777, 8888888);
   TestInt32Binop(kExprI32Mul, 65130756, 88734, 734);
@@ -217,7 +203,6 @@
   TestInt32Binop(kExprI32GeU, 1, 0xF0000000, 98978);
 }
 
-
 void TestInt32Unop(WasmOpcode opcode, int32_t expected, int32_t a) {
   {
     WasmRunner<int32_t> r;
@@ -233,8 +218,7 @@
   }
 }
 
-
-TEST(Run_WasmInt32Clz) {
+WASM_EXEC_TEST(Int32Clz) {
   TestInt32Unop(kExprI32Clz, 0, 0x80001000);
   TestInt32Unop(kExprI32Clz, 1, 0x40000500);
   TestInt32Unop(kExprI32Clz, 2, 0x20000300);
@@ -270,8 +254,7 @@
   TestInt32Unop(kExprI32Clz, 32, 0x00000000);
 }
 
-
-TEST(Run_WasmInt32Ctz) {
+WASM_EXEC_TEST(Int32Ctz) {
   TestInt32Unop(kExprI32Ctz, 32, 0x00000000);
   TestInt32Unop(kExprI32Ctz, 31, 0x80000000);
   TestInt32Unop(kExprI32Ctz, 30, 0x40000000);
@@ -307,8 +290,7 @@
   TestInt32Unop(kExprI32Ctz, 0, 0x9afdbc81);
 }
 
-
-TEST(Run_WasmInt32Popcnt) {
+WASM_EXEC_TEST(Int32Popcnt) {
   TestInt32Unop(kExprI32Popcnt, 32, 0xffffffff);
   TestInt32Unop(kExprI32Popcnt, 0, 0x00000000);
   TestInt32Unop(kExprI32Popcnt, 1, 0x00008000);
@@ -316,7 +298,7 @@
   TestInt32Unop(kExprI32Popcnt, 19, 0xfedcba09);
 }
 
-TEST(Run_WasmI32Eqz) {
+WASM_EXEC_TEST(I32Eqz) {
   TestInt32Unop(kExprI32Eqz, 0, 1);
   TestInt32Unop(kExprI32Eqz, 0, -1);
   TestInt32Unop(kExprI32Eqz, 0, -827343);
@@ -324,7 +306,7 @@
   TestInt32Unop(kExprI32Eqz, 1, 0);
 }
 
-TEST(Run_WasmI32Shl) {
+WASM_EXEC_TEST(I32Shl) {
   WasmRunner<uint32_t> r(MachineType::Uint32(), MachineType::Uint32());
   BUILD(r, WASM_I32_SHL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
@@ -336,7 +318,7 @@
   }
 }
 
-TEST(Run_WasmI32Shr) {
+WASM_EXEC_TEST(I32Shr) {
   WasmRunner<uint32_t> r(MachineType::Uint32(), MachineType::Uint32());
   BUILD(r, WASM_I32_SHR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
@@ -348,7 +330,7 @@
   }
 }
 
-TEST(Run_WasmI32Sar) {
+WASM_EXEC_TEST(I32Sar) {
   WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
   BUILD(r, WASM_I32_SAR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
@@ -360,7 +342,7 @@
   }
 }
 
-TEST(Run_WASM_Int32DivS_trap) {
+WASM_EXEC_TEST(Int32DivS_trap) {
   WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
   BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   const int32_t kMin = std::numeric_limits<int32_t>::min();
@@ -371,8 +353,7 @@
   CHECK_TRAP(r.Call(kMin, 0));
 }
 
-
-TEST(Run_WASM_Int32RemS_trap) {
+WASM_EXEC_TEST(Int32RemS_trap) {
   WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
   BUILD(r, WASM_I32_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   const int32_t kMin = std::numeric_limits<int32_t>::min();
@@ -383,8 +364,7 @@
   CHECK_TRAP(r.Call(kMin, 0));
 }
 
-
-TEST(Run_WASM_Int32DivU_trap) {
+WASM_EXEC_TEST(Int32DivU_trap) {
   WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
   BUILD(r, WASM_I32_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   const int32_t kMin = std::numeric_limits<int32_t>::min();
@@ -395,8 +375,7 @@
   CHECK_TRAP(r.Call(kMin, 0));
 }
 
-
-TEST(Run_WASM_Int32RemU_trap) {
+WASM_EXEC_TEST(Int32RemU_trap) {
   WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
   BUILD(r, WASM_I32_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   CHECK_EQ(17, r.Call(217, 100));
@@ -407,60 +386,7 @@
   CHECK_EQ(kMin, r.Call(kMin, -1));
 }
 
-TEST(Run_WASM_Int32DivS_asmjs) {
-  TestingModule module;
-  module.origin = kAsmJsOrigin;
-  WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
-  BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  const int32_t kMin = std::numeric_limits<int32_t>::min();
-  CHECK_EQ(0, r.Call(0, 100));
-  CHECK_EQ(0, r.Call(100, 0));
-  CHECK_EQ(0, r.Call(-1001, 0));
-  CHECK_EQ(kMin, r.Call(kMin, -1));
-  CHECK_EQ(0, r.Call(kMin, 0));
-}
-
-TEST(Run_WASM_Int32RemS_asmjs) {
-  TestingModule module;
-  module.origin = kAsmJsOrigin;
-  WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
-  BUILD(r, WASM_I32_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  const int32_t kMin = std::numeric_limits<int32_t>::min();
-  CHECK_EQ(33, r.Call(133, 100));
-  CHECK_EQ(0, r.Call(kMin, -1));
-  CHECK_EQ(0, r.Call(100, 0));
-  CHECK_EQ(0, r.Call(-1001, 0));
-  CHECK_EQ(0, r.Call(kMin, 0));
-}
-
-TEST(Run_WASM_Int32DivU_asmjs) {
-  TestingModule module;
-  module.origin = kAsmJsOrigin;
-  WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
-  BUILD(r, WASM_I32_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  const int32_t kMin = std::numeric_limits<int32_t>::min();
-  CHECK_EQ(0, r.Call(0, 100));
-  CHECK_EQ(0, r.Call(kMin, -1));
-  CHECK_EQ(0, r.Call(100, 0));
-  CHECK_EQ(0, r.Call(-1001, 0));
-  CHECK_EQ(0, r.Call(kMin, 0));
-}
-
-TEST(Run_WASM_Int32RemU_asmjs) {
-  TestingModule module;
-  module.origin = kAsmJsOrigin;
-  WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
-  BUILD(r, WASM_I32_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  const int32_t kMin = std::numeric_limits<int32_t>::min();
-  CHECK_EQ(17, r.Call(217, 100));
-  CHECK_EQ(0, r.Call(100, 0));
-  CHECK_EQ(0, r.Call(-1001, 0));
-  CHECK_EQ(0, r.Call(kMin, 0));
-  CHECK_EQ(kMin, r.Call(kMin, -1));
-}
-
-
-TEST(Run_WASM_Int32DivS_byzero_const) {
+WASM_EXEC_TEST(Int32DivS_byzero_const) {
   for (int8_t denom = -2; denom < 8; denom++) {
     WasmRunner<int32_t> r(MachineType::Int32());
     BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_I8(denom)));
@@ -474,8 +400,7 @@
   }
 }
 
-
-TEST(Run_WASM_Int32DivU_byzero_const) {
+WASM_EXEC_TEST(Int32DivU_byzero_const) {
   for (uint32_t denom = 0xfffffffe; denom < 8; denom++) {
     WasmRunner<uint32_t> r(MachineType::Uint32());
     BUILD(r, WASM_I32_DIVU(WASM_GET_LOCAL(0), WASM_I32V_1(denom)));
@@ -490,8 +415,7 @@
   }
 }
 
-
-TEST(Run_WASM_Int32DivS_trap_effect) {
+WASM_EXEC_TEST(Int32DivS_trap_effect) {
   TestingModule module;
   module.AddMemoryElems<int32_t>(8);
   WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
@@ -525,7 +449,6 @@
   }
 }
 
-
 void TestFloat32BinopWithConvert(WasmOpcode opcode, int32_t expected, float a,
                                  float b) {
   {
@@ -544,7 +467,6 @@
   }
 }
 
-
 void TestFloat32UnopWithConvert(WasmOpcode opcode, int32_t expected, float a) {
   {
     WasmRunner<int32_t> r;
@@ -560,7 +482,6 @@
   }
 }
 
-
 void TestFloat64Binop(WasmOpcode opcode, int32_t expected, double a, double b) {
   {
     WasmRunner<int32_t> r;
@@ -576,7 +497,6 @@
   }
 }
 
-
 void TestFloat64BinopWithConvert(WasmOpcode opcode, int32_t expected, double a,
                                  double b) {
   {
@@ -594,7 +514,6 @@
   }
 }
 
-
 void TestFloat64UnopWithConvert(WasmOpcode opcode, int32_t expected, double a) {
   {
     WasmRunner<int32_t> r;
@@ -610,7 +529,7 @@
   }
 }
 
-TEST(Run_WasmFloat32Binops) {
+WASM_EXEC_TEST(Float32Binops) {
   TestFloat32Binop(kExprF32Eq, 1, 8.125f, 8.125f);
   TestFloat32Binop(kExprF32Ne, 1, 8.125f, 8.127f);
   TestFloat32Binop(kExprF32Lt, 1, -9.5f, -9.0f);
@@ -624,14 +543,14 @@
   TestFloat32BinopWithConvert(kExprF32Div, 11, 22.1f, 2.0f);
 }
 
-TEST(Run_WasmFloat32Unops) {
+WASM_EXEC_TEST(Float32Unops) {
   TestFloat32UnopWithConvert(kExprF32Abs, 8, 8.125f);
   TestFloat32UnopWithConvert(kExprF32Abs, 9, -9.125f);
   TestFloat32UnopWithConvert(kExprF32Neg, -213, 213.125f);
   TestFloat32UnopWithConvert(kExprF32Sqrt, 12, 144.4f);
 }
 
-TEST(Run_WasmFloat64Binops) {
+WASM_EXEC_TEST(Float64Binops) {
   TestFloat64Binop(kExprF64Eq, 1, 16.25, 16.25);
   TestFloat64Binop(kExprF64Ne, 1, 16.25, 16.15);
   TestFloat64Binop(kExprF64Lt, 1, -32.4, 11.7);
@@ -645,14 +564,14 @@
   TestFloat64BinopWithConvert(kExprF64Div, -1111, -2222.3, 2);
 }
 
-TEST(Run_WasmFloat64Unops) {
+WASM_EXEC_TEST(Float64Unops) {
   TestFloat64UnopWithConvert(kExprF64Abs, 108, 108.125);
   TestFloat64UnopWithConvert(kExprF64Abs, 209, -209.125);
   TestFloat64UnopWithConvert(kExprF64Neg, -209, 209.125);
   TestFloat64UnopWithConvert(kExprF64Sqrt, 13, 169.4);
 }
 
-TEST(Run_WasmFloat32Neg) {
+WASM_EXEC_TEST(Float32Neg) {
   WasmRunner<float> r(MachineType::Float32());
   BUILD(r, WASM_F32_NEG(WASM_GET_LOCAL(0)));
 
@@ -662,8 +581,22 @@
   }
 }
 
+WASM_EXEC_TEST(Float32SubMinusZero) {
+  WasmRunner<float> r(MachineType::Float32());
+  BUILD(r, WASM_F32_SUB(WASM_F32(-0.0), WASM_GET_LOCAL(0)));
 
-TEST(Run_WasmFloat64Neg) {
+  CHECK_EQ(0x7fe00000, bit_cast<uint32_t>(r.Call(bit_cast<float>(0x7fa00000))));
+}
+
+WASM_EXEC_TEST(Float64SubMinusZero) {
+  WasmRunner<double> r(MachineType::Float64());
+  BUILD(r, WASM_F64_SUB(WASM_F64(-0.0), WASM_GET_LOCAL(0)));
+
+  CHECK_EQ(0x7ff8123456789abc,
+           bit_cast<uint64_t>(r.Call(bit_cast<double>(0x7ff0123456789abc))));
+}
+
+WASM_EXEC_TEST(Float64Neg) {
   WasmRunner<double> r(MachineType::Float64());
   BUILD(r, WASM_F64_NEG(WASM_GET_LOCAL(0)));
 
@@ -673,8 +606,7 @@
   }
 }
 
-
-TEST(Run_Wasm_IfElse_P) {
+WASM_EXEC_TEST(IfElse_P) {
   WasmRunner<int32_t> r(MachineType::Int32());
   // if (p0) return 11; else return 22;
   BUILD(r, WASM_IF_ELSE(WASM_GET_LOCAL(0),  // --
@@ -686,8 +618,53 @@
   }
 }
 
+WASM_EXEC_TEST(If_empty1) {
+  WasmRunner<uint32_t> r(MachineType::Uint32(), MachineType::Uint32());
+  BUILD(r, WASM_GET_LOCAL(0), kExprIf, kExprEnd, WASM_GET_LOCAL(1));
+  FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i - 9, *i)); }
+}
 
-TEST(Run_Wasm_IfElse_Unreachable1) {
+WASM_EXEC_TEST(IfElse_empty1) {
+  WasmRunner<uint32_t> r(MachineType::Uint32(), MachineType::Uint32());
+  BUILD(r, WASM_GET_LOCAL(0), kExprIf, kExprElse, kExprEnd, WASM_GET_LOCAL(1));
+  FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i - 8, *i)); }
+}
+
+WASM_EXEC_TEST(IfElse_empty2) {
+  WasmRunner<uint32_t> r(MachineType::Uint32(), MachineType::Uint32());
+  BUILD(r, WASM_GET_LOCAL(0), kExprIf, WASM_ZERO, kExprElse, kExprEnd,
+        WASM_GET_LOCAL(1));
+  FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i - 7, *i)); }
+}
+
+WASM_EXEC_TEST(IfElse_empty3) {
+  WasmRunner<uint32_t> r(MachineType::Uint32(), MachineType::Uint32());
+  BUILD(r, WASM_GET_LOCAL(0), kExprIf, kExprElse, WASM_ZERO, kExprEnd,
+        WASM_GET_LOCAL(1));
+  FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i - 6, *i)); }
+}
+
+WASM_EXEC_TEST(If_chain) {
+  WasmRunner<int32_t> r(MachineType::Int32());
+  // if (p0) 13; if (p0) 14; 15
+  BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_I8(13)),
+        WASM_IF(WASM_GET_LOCAL(0), WASM_I8(14)), WASM_I8(15));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(15, r.Call(*i)); }
+}
+
+WASM_EXEC_TEST(If_chain_set) {
+  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+  // if (p0) p1 = 73; if (p0) p1 = 74; p1
+  BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(1, WASM_I8(73))),
+        WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(1, WASM_I8(74))),
+        WASM_GET_LOCAL(1));
+  FOR_INT32_INPUTS(i) {
+    int32_t expected = *i ? 74 : *i;
+    CHECK_EQ(expected, r.Call(*i, *i));
+  }
+}
+
+WASM_EXEC_TEST(IfElse_Unreachable1) {
   WasmRunner<int32_t> r;
   // if (0) unreachable; else return 22;
   BUILD(r, WASM_IF_ELSE(WASM_ZERO,         // --
@@ -696,24 +673,21 @@
   CHECK_EQ(27, r.Call());
 }
 
-
-TEST(Run_Wasm_Return12) {
+WASM_EXEC_TEST(Return12) {
   WasmRunner<int32_t> r;
 
   BUILD(r, RET_I8(12));
   CHECK_EQ(12, r.Call());
 }
 
-
-TEST(Run_Wasm_Return17) {
+WASM_EXEC_TEST(Return17) {
   WasmRunner<int32_t> r;
 
   BUILD(r, B1(RET_I8(17)));
   CHECK_EQ(17, r.Call());
 }
 
-
-TEST(Run_Wasm_Return_I32) {
+WASM_EXEC_TEST(Return_I32) {
   WasmRunner<int32_t> r(MachineType::Int32());
 
   BUILD(r, RET(WASM_GET_LOCAL(0)));
@@ -721,8 +695,7 @@
   FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
 }
 
-
-TEST(Run_Wasm_Return_F32) {
+WASM_EXEC_TEST(Return_F32) {
   WasmRunner<float> r(MachineType::Float32());
 
   BUILD(r, RET(WASM_GET_LOCAL(0)));
@@ -738,8 +711,7 @@
   }
 }
 
-
-TEST(Run_Wasm_Return_F64) {
+WASM_EXEC_TEST(Return_F64) {
   WasmRunner<double> r(MachineType::Float64());
 
   BUILD(r, RET(WASM_GET_LOCAL(0)));
@@ -755,8 +727,7 @@
   }
 }
 
-
-TEST(Run_Wasm_Select) {
+WASM_EXEC_TEST(Select) {
   WasmRunner<int32_t> r(MachineType::Int32());
   // return select(11, 22, a);
   BUILD(r, WASM_SELECT(WASM_I8(11), WASM_I8(22), WASM_GET_LOCAL(0)));
@@ -766,8 +737,7 @@
   }
 }
 
-
-TEST(Run_Wasm_Select_strict1) {
+WASM_EXEC_TEST(Select_strict1) {
   WasmRunner<int32_t> r(MachineType::Int32());
   // select(a=0, a=1, a=2); return a
   BUILD(r, B2(WASM_SELECT(WASM_SET_LOCAL(0, WASM_I8(0)),
@@ -777,8 +747,7 @@
   FOR_INT32_INPUTS(i) { CHECK_EQ(2, r.Call(*i)); }
 }
 
-
-TEST(Run_Wasm_Select_strict2) {
+WASM_EXEC_TEST(Select_strict2) {
   WasmRunner<int32_t> r(MachineType::Int32());
   r.AllocateLocal(kAstI32);
   r.AllocateLocal(kAstI32);
@@ -791,7 +760,7 @@
   }
 }
 
-TEST(Run_Wasm_Select_strict3) {
+WASM_EXEC_TEST(Select_strict3) {
   WasmRunner<int32_t> r(MachineType::Int32());
   r.AllocateLocal(kAstI32);
   r.AllocateLocal(kAstI32);
@@ -805,8 +774,7 @@
   }
 }
 
-
-TEST(Run_Wasm_BrIf_strict) {
+WASM_EXEC_TEST(BrIf_strict) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(
       r,
@@ -816,14 +784,14 @@
   FOR_INT32_INPUTS(i) { CHECK_EQ(99, r.Call(*i)); }
 }
 
-TEST(Run_Wasm_BrTable0a) {
+WASM_EXEC_TEST(BrTable0a) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r,
         B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0))), WASM_I8(91)));
   FOR_INT32_INPUTS(i) { CHECK_EQ(91, r.Call(*i)); }
 }
 
-TEST(Run_Wasm_BrTable0b) {
+WASM_EXEC_TEST(BrTable0b) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r,
         B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(0), BR_TARGET(0))),
@@ -831,7 +799,7 @@
   FOR_INT32_INPUTS(i) { CHECK_EQ(92, r.Call(*i)); }
 }
 
-TEST(Run_Wasm_BrTable0c) {
+WASM_EXEC_TEST(BrTable0c) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(
       r,
@@ -844,13 +812,13 @@
   }
 }
 
-TEST(Run_Wasm_BrTable1) {
+WASM_EXEC_TEST(BrTable1) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0))), RET_I8(93));
   FOR_INT32_INPUTS(i) { CHECK_EQ(93, r.Call(*i)); }
 }
 
-TEST(Run_Wasm_BrTable_loop) {
+WASM_EXEC_TEST(BrTable_loop) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r,
         B2(WASM_LOOP(1, WASM_BR_TABLE(WASM_INC_LOCAL_BY(0, 1), 2, BR_TARGET(2),
@@ -864,7 +832,7 @@
   CHECK_EQ(98, r.Call(-100));
 }
 
-TEST(Run_Wasm_BrTable_br) {
+WASM_EXEC_TEST(BrTable_br) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r,
         B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(1), BR_TARGET(0))),
@@ -876,7 +844,7 @@
   CHECK_EQ(91, r.Call(3));
 }
 
-TEST(Run_Wasm_BrTable_br2) {
+WASM_EXEC_TEST(BrTable_br2) {
   WasmRunner<int32_t> r(MachineType::Int32());
 
   BUILD(r, B2(B2(B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 3, BR_TARGET(1),
@@ -893,7 +861,7 @@
   CHECK_EQ(85, r.Call(5));
 }
 
-TEST(Run_Wasm_BrTable4) {
+WASM_EXEC_TEST(BrTable4) {
   for (int i = 0; i < 4; i++) {
     for (int t = 0; t < 4; t++) {
       uint32_t cases[] = {0, 1, 2, 3};
@@ -920,7 +888,7 @@
   }
 }
 
-TEST(Run_Wasm_BrTable4x4) {
+WASM_EXEC_TEST(BrTable4x4) {
   for (byte a = 0; a < 4; a++) {
     for (byte b = 0; b < 4; b++) {
       for (byte c = 0; c < 4; c++) {
@@ -953,7 +921,7 @@
   }
 }
 
-TEST(Run_Wasm_BrTable4_fallthru) {
+WASM_EXEC_TEST(BrTable4_fallthru) {
   byte code[] = {
       B2(B2(B2(B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 3, BR_TARGET(0),
                                    BR_TARGET(1), BR_TARGET(2), BR_TARGET(3))),
@@ -979,7 +947,7 @@
   CHECK_EQ(108, r.Call(4, 100));
 }
 
-TEST(Run_Wasm_F32ReinterpretI32) {
+WASM_EXEC_TEST(F32ReinterpretI32) {
   TestingModule module;
   int32_t* memory = module.AddMemoryElems<int32_t>(8);
   WasmRunner<int32_t> r(&module);
@@ -994,8 +962,7 @@
   }
 }
 
-
-TEST(Run_Wasm_I32ReinterpretF32) {
+WASM_EXEC_TEST(I32ReinterpretF32) {
   TestingModule module;
   int32_t* memory = module.AddMemoryElems<int32_t>(8);
   WasmRunner<int32_t> r(&module, MachineType::Int32());
@@ -1012,8 +979,7 @@
   }
 }
 
-
-TEST(Run_Wasm_ReturnStore) {
+WASM_EXEC_TEST(ReturnStore) {
   TestingModule module;
   int32_t* memory = module.AddMemoryElems<int32_t>(8);
   WasmRunner<int32_t> r(&module);
@@ -1028,8 +994,7 @@
   }
 }
 
-
-TEST(Run_Wasm_VoidReturn1) {
+WASM_EXEC_TEST(VoidReturn1) {
   // We use a wrapper function because WasmRunner<void> does not exist.
 
   // Build the test function.
@@ -1048,8 +1013,7 @@
   CHECK_EQ(kExpected, result);
 }
 
-
-TEST(Run_Wasm_VoidReturn2) {
+WASM_EXEC_TEST(VoidReturn2) {
   // We use a wrapper function because WasmRunner<void> does not exist.
   // Build the test function.
   TestSignatures sigs;
@@ -1067,13 +1031,42 @@
   CHECK_EQ(kExpected, result);
 }
 
+WASM_EXEC_TEST(Block_empty) {
+  WasmRunner<int32_t> r(MachineType::Int32());
+  BUILD(r, kExprBlock, kExprEnd, WASM_GET_LOCAL(0));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
+}
 
-TEST(Run_Wasm_Block_If_P) {
+WASM_EXEC_TEST(Block_empty_br1) {
+  WasmRunner<int32_t> r(MachineType::Int32());
+  BUILD(r, B1(WASM_BR(0)), WASM_GET_LOCAL(0));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
+}
+
+WASM_EXEC_TEST(Block_empty_brif1) {
+  WasmRunner<int32_t> r(MachineType::Int32());
+  BUILD(r, B1(WASM_BR_IF(0, WASM_ZERO)), WASM_GET_LOCAL(0));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
+}
+
+WASM_EXEC_TEST(Block_empty_brif2) {
+  WasmRunner<uint32_t> r(MachineType::Uint32(), MachineType::Uint32());
+  BUILD(r, B1(WASM_BR_IF(0, WASM_GET_LOCAL(1))), WASM_GET_LOCAL(0));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i, *i + 1)); }
+}
+
+WASM_EXEC_TEST(Block_br2) {
+  WasmRunner<int32_t> r(MachineType::Int32());
+  BUILD(r, B1(WASM_BRV(0, WASM_GET_LOCAL(0))));
+  FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
+}
+
+WASM_EXEC_TEST(Block_If_P) {
   WasmRunner<int32_t> r(MachineType::Int32());
   // { if (p0) return 51; return 52; }
   BUILD(r, B2(                                     // --
                WASM_IF(WASM_GET_LOCAL(0),          // --
-                       WASM_BRV(0, WASM_I8(51))),  // --
+                       WASM_BRV(1, WASM_I8(51))),  // --
                WASM_I8(52)));                      // --
   FOR_INT32_INPUTS(i) {
     int32_t expected = *i ? 51 : 52;
@@ -1081,8 +1074,31 @@
   }
 }
 
+WASM_EXEC_TEST(Loop_empty) {
+  WasmRunner<int32_t> r(MachineType::Int32());
+  BUILD(r, kExprLoop, kExprEnd, WASM_GET_LOCAL(0));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
+}
 
-TEST(Run_Wasm_Block_BrIf_P) {
+WASM_EXEC_TEST(Loop_empty_br1) {
+  WasmRunner<int32_t> r(MachineType::Int32());
+  BUILD(r, WASM_LOOP(1, WASM_BR(1)), WASM_GET_LOCAL(0));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
+}
+
+WASM_EXEC_TEST(Loop_empty_brif1) {
+  WasmRunner<int32_t> r(MachineType::Int32());
+  BUILD(r, WASM_LOOP(1, WASM_BR_IF(1, WASM_ZERO)), WASM_GET_LOCAL(0));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
+}
+
+WASM_EXEC_TEST(Loop_empty_brif2) {
+  WasmRunner<uint32_t> r(MachineType::Uint32(), MachineType::Uint32());
+  BUILD(r, WASM_LOOP(1, WASM_BR_IF(1, WASM_GET_LOCAL(1))), WASM_GET_LOCAL(0));
+  FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i, *i + 1)); }
+}
+
+WASM_EXEC_TEST(Block_BrIf_P) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, B2(WASM_BRV_IF(0, WASM_I8(51), WASM_GET_LOCAL(0)), WASM_I8(52)));
   FOR_INT32_INPUTS(i) {
@@ -1091,8 +1107,7 @@
   }
 }
 
-
-TEST(Run_Wasm_Block_IfElse_P_assign) {
+WASM_EXEC_TEST(Block_IfElse_P_assign) {
   WasmRunner<int32_t> r(MachineType::Int32());
   // { if (p0) p0 = 71; else p0 = 72; return p0; }
   BUILD(r, B2(                                                // --
@@ -1106,8 +1121,7 @@
   }
 }
 
-
-TEST(Run_Wasm_Block_IfElse_P_return) {
+WASM_EXEC_TEST(Block_IfElse_P_return) {
   WasmRunner<int32_t> r(MachineType::Int32());
   // if (p0) return 81; else return 82;
   BUILD(r,                               // --
@@ -1120,8 +1134,7 @@
   }
 }
 
-
-TEST(Run_Wasm_Block_If_P_assign) {
+WASM_EXEC_TEST(Block_If_P_assign) {
   WasmRunner<int32_t> r(MachineType::Int32());
   // { if (p0) p0 = 61; p0; }
   BUILD(r, WASM_BLOCK(
@@ -1133,16 +1146,14 @@
   }
 }
 
-
-TEST(Run_Wasm_DanglingAssign) {
+WASM_EXEC_TEST(DanglingAssign) {
   WasmRunner<int32_t> r(MachineType::Int32());
   // { return 0; p0 = 0; }
   BUILD(r, B2(RET_I8(99), WASM_SET_LOCAL(0, WASM_ZERO)));
   CHECK_EQ(99, r.Call(1));
 }
 
-
-TEST(Run_Wasm_ExprIf_P) {
+WASM_EXEC_TEST(ExprIf_P) {
   WasmRunner<int32_t> r(MachineType::Int32());
   // p0 ? 11 : 22;
   BUILD(r, WASM_IF_ELSE(WASM_GET_LOCAL(0),  // --
@@ -1154,8 +1165,7 @@
   }
 }
 
-
-TEST(Run_Wasm_ExprIf_P_fallthru) {
+WASM_EXEC_TEST(ExprIf_P_fallthru) {
   WasmRunner<int32_t> r(MachineType::Int32());
   // p0 ? 11 : 22;
   BUILD(r, WASM_IF_ELSE(WASM_GET_LOCAL(0),  // --
@@ -1167,14 +1177,13 @@
   }
 }
 
-
-TEST(Run_Wasm_CountDown) {
+WASM_EXEC_TEST(CountDown) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r,
         WASM_BLOCK(
             2, WASM_LOOP(
                    1, WASM_IF(WASM_GET_LOCAL(0),
-                              WASM_BRV(0, WASM_SET_LOCAL(
+                              WASM_BRV(1, WASM_SET_LOCAL(
                                               0, WASM_I32_SUB(WASM_GET_LOCAL(0),
                                                               WASM_I8(1)))))),
             WASM_GET_LOCAL(0)));
@@ -1183,12 +1192,11 @@
   CHECK_EQ(0, r.Call(100));
 }
 
-
-TEST(Run_Wasm_CountDown_fallthru) {
+WASM_EXEC_TEST(CountDown_fallthru) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r,
         WASM_BLOCK(
-            2, WASM_LOOP(3, WASM_IF(WASM_NOT(WASM_GET_LOCAL(0)), WASM_BREAK(0)),
+            2, WASM_LOOP(3, WASM_IF(WASM_NOT(WASM_GET_LOCAL(0)), WASM_BREAK(1)),
                          WASM_SET_LOCAL(
                              0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(1))),
                          WASM_CONTINUE(0)),
@@ -1198,8 +1206,7 @@
   CHECK_EQ(0, r.Call(100));
 }
 
-
-TEST(Run_Wasm_WhileCountDown) {
+WASM_EXEC_TEST(WhileCountDown) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, WASM_BLOCK(
                2, WASM_WHILE(WASM_GET_LOCAL(0),
@@ -1211,10 +1218,9 @@
   CHECK_EQ(0, r.Call(100));
 }
 
-
-TEST(Run_Wasm_Loop_if_break1) {
+WASM_EXEC_TEST(Loop_if_break1) {
   WasmRunner<int32_t> r(MachineType::Int32());
-  BUILD(r, B2(WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(0)),
+  BUILD(r, B2(WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(1)),
                         WASM_SET_LOCAL(0, WASM_I8(99))),
               WASM_GET_LOCAL(0)));
   CHECK_EQ(99, r.Call(0));
@@ -1223,8 +1229,7 @@
   CHECK_EQ(-29, r.Call(-29));
 }
 
-
-TEST(Run_Wasm_Loop_if_break2) {
+WASM_EXEC_TEST(Loop_if_break2) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, B2(WASM_LOOP(2, WASM_BR_IF(1, WASM_GET_LOCAL(0)),
                         WASM_SET_LOCAL(0, WASM_I8(99))),
@@ -1235,8 +1240,7 @@
   CHECK_EQ(-29, r.Call(-29));
 }
 
-
-TEST(Run_Wasm_Loop_if_break_fallthru) {
+WASM_EXEC_TEST(Loop_if_break_fallthru) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, B1(WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(1)),
                         WASM_SET_LOCAL(0, WASM_I8(93)))),
@@ -1247,8 +1251,25 @@
   CHECK_EQ(-22, r.Call(-22));
 }
 
+WASM_EXEC_TEST(IfBreak1) {
+  WasmRunner<int32_t> r(MachineType::Int32());
+  BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_SEQ(WASM_BR(0), WASM_UNREACHABLE)),
+        WASM_I8(91));
+  CHECK_EQ(91, r.Call(0));
+  CHECK_EQ(91, r.Call(1));
+  CHECK_EQ(91, r.Call(-8734));
+}
 
-TEST(Run_Wasm_LoadMemI32) {
+WASM_EXEC_TEST(IfBreak2) {
+  WasmRunner<int32_t> r(MachineType::Int32());
+  BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_SEQ(WASM_BR(0), RET_I8(77))),
+        WASM_I8(81));
+  CHECK_EQ(81, r.Call(0));
+  CHECK_EQ(81, r.Call(1));
+  CHECK_EQ(81, r.Call(-8734));
+}
+
+WASM_EXEC_TEST(LoadMemI32) {
   TestingModule module;
   int32_t* memory = module.AddMemoryElems<int32_t>(8);
   WasmRunner<int32_t> r(&module, MachineType::Int32());
@@ -1266,8 +1287,7 @@
   CHECK_EQ(77777777, r.Call(0));
 }
 
-
-TEST(Run_Wasm_LoadMemI32_oob) {
+WASM_EXEC_TEST(LoadMemI32_oob) {
   TestingModule module;
   int32_t* memory = module.AddMemoryElems<int32_t>(8);
   WasmRunner<int32_t> r(&module, MachineType::Uint32());
@@ -1286,30 +1306,7 @@
   }
 }
 
-
-TEST(Run_Wasm_LoadMemI32_oob_asm) {
-  TestingModule module;
-  module.origin = kAsmJsOrigin;
-  int32_t* memory = module.AddMemoryElems<int32_t>(8);
-  WasmRunner<int32_t> r(&module, MachineType::Uint32());
-  module.RandomizeMemory(1112);
-
-  BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0)));
-
-  memory[0] = 999999;
-  CHECK_EQ(999999, r.Call(0u));
-  // TODO(titzer): offset 29-31 should also be OOB.
-  for (uint32_t offset = 32; offset < 40; offset++) {
-    CHECK_EQ(0, r.Call(offset));
-  }
-
-  for (uint32_t offset = 0x80000000; offset < 0x80000010; offset++) {
-    CHECK_EQ(0, r.Call(offset));
-  }
-}
-
-
-TEST(Run_Wasm_LoadMem_offset_oob) {
+WASM_EXEC_TEST(LoadMem_offset_oob) {
   TestingModule module;
   module.AddMemoryElems<int32_t>(8);
 
@@ -1335,8 +1332,7 @@
   }
 }
 
-
-TEST(Run_Wasm_LoadMemI32_offset) {
+WASM_EXEC_TEST(LoadMemI32_offset) {
   TestingModule module;
   int32_t* memory = module.AddMemoryElems<int32_t>(4);
   WasmRunner<int32_t> r(&module, MachineType::Int32());
@@ -1361,10 +1357,9 @@
   CHECK_EQ(44444444, r.Call(8));
 }
 
-
 #if !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_MIPS64
 
-TEST(Run_Wasm_LoadMemI32_const_oob_misaligned) {
+WASM_EXEC_TEST(LoadMemI32_const_oob_misaligned) {
   const int kMemSize = 12;
   // TODO(titzer): Fix misaligned accesses on MIPS and re-enable.
   for (int offset = 0; offset < kMemSize + 5; offset++) {
@@ -1389,8 +1384,7 @@
 
 #endif
 
-
-TEST(Run_Wasm_LoadMemI32_const_oob) {
+WASM_EXEC_TEST(LoadMemI32_const_oob) {
   const int kMemSize = 24;
   for (int offset = 0; offset < kMemSize + 5; offset += 4) {
     for (int index = 0; index < kMemSize + 5; index += 4) {
@@ -1412,8 +1406,7 @@
   }
 }
 
-
-TEST(Run_Wasm_StoreMemI32_offset) {
+WASM_EXEC_TEST(StoreMemI32_offset) {
   TestingModule module;
   int32_t* memory = module.AddMemoryElems<int32_t>(4);
   WasmRunner<int32_t> r(&module, MachineType::Int32());
@@ -1436,8 +1429,7 @@
   }
 }
 
-
-TEST(Run_Wasm_StoreMem_offset_oob) {
+WASM_EXEC_TEST(StoreMem_offset_oob) {
   TestingModule module;
   byte* memory = module.AddMemoryElems<byte>(32);
 
@@ -1473,8 +1465,7 @@
   }
 }
 
-
-TEST(Run_Wasm_LoadMemI32_P) {
+WASM_EXEC_TEST(LoadMemI32_P) {
   const int kNumElems = 8;
   TestingModule module;
   int32_t* memory = module.AddMemoryElems<int32_t>(kNumElems);
@@ -1488,8 +1479,7 @@
   }
 }
 
-
-TEST(Run_Wasm_MemI32_Sum) {
+WASM_EXEC_TEST(MemI32_Sum) {
   const int kNumElems = 20;
   TestingModule module;
   uint32_t* memory = module.AddMemoryElems<uint32_t>(kNumElems);
@@ -1521,24 +1511,22 @@
   }
 }
 
-
-TEST(Run_Wasm_CheckMachIntsZero) {
+WASM_EXEC_TEST(CheckMachIntsZero) {
   const int kNumElems = 55;
   TestingModule module;
   module.AddMemoryElems<uint32_t>(kNumElems);
   WasmRunner<uint32_t> r(&module, MachineType::Int32());
 
-  BUILD(r, kExprBlock, 2, kExprLoop, 1, kExprIf, kExprGetLocal, 0, kExprBr, 0,
-        kExprIfElse, kExprI32LoadMem, ZERO_ALIGNMENT, ZERO_OFFSET,
-        kExprGetLocal, 0, kExprBr, 2, kExprI8Const, 255, kExprSetLocal, 0,
-        kExprI32Sub, kExprGetLocal, 0, kExprI8Const, 4, kExprI8Const, 0);
+  BUILD(r, kExprLoop, kExprGetLocal, 0, kExprIf, kExprGetLocal, 0,
+        kExprI32LoadMem, 0, 0, kExprIf, kExprI8Const, 255, kExprReturn, ARITY_1,
+        kExprEnd, kExprGetLocal, 0, kExprI8Const, 4, kExprI32Sub, kExprSetLocal,
+        0, kExprBr, ARITY_1, DEPTH_0, kExprEnd, kExprEnd, kExprI8Const, 0);
 
   module.BlankMemory();
   CHECK_EQ(0, r.Call((kNumElems - 1) * 4));
 }
 
-
-TEST(Run_Wasm_MemF32_Sum) {
+WASM_EXEC_TEST(MemF32_Sum) {
   const int kSize = 5;
   TestingModule module;
   module.AddMemoryElems<float>(kSize);
@@ -1571,7 +1559,6 @@
   CHECK_EQ(71256.0f, buffer[0]);
 }
 
-
 template <typename T>
 T GenerateAndRunFold(WasmOpcode binop, T* buffer, size_t size,
                      LocalType astType, MachineType memType) {
@@ -1602,8 +1589,7 @@
   return module.raw_mem_at<double>(0);
 }
 
-
-TEST(Run_Wasm_MemF64_Mul) {
+WASM_EXEC_TEST(MemF64_Mul) {
   const size_t kSize = 6;
   double buffer[kSize] = {1, 2, 2, 2, 2, 2};
   double result = GenerateAndRunFold<double>(kExprF64Mul, buffer, kSize,
@@ -1611,14 +1597,12 @@
   CHECK_EQ(32, result);
 }
 
-
 TEST(Build_Wasm_Infinite_Loop) {
   WasmRunner<int32_t> r(MachineType::Int32());
   // Only build the graph and compile, don't run.
   BUILD(r, WASM_INFINITE_LOOP);
 }
 
-
 TEST(Build_Wasm_Infinite_Loop_effect) {
   TestingModule module;
   module.AddMemoryElems<int8_t>(16);
@@ -1628,55 +1612,47 @@
   BUILD(r, WASM_LOOP(1, WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)));
 }
 
-
-TEST(Run_Wasm_Unreachable0a) {
+WASM_EXEC_TEST(Unreachable0a) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, B2(WASM_BRV(0, WASM_I8(9)), RET(WASM_GET_LOCAL(0))));
   CHECK_EQ(9, r.Call(0));
   CHECK_EQ(9, r.Call(1));
 }
 
-
-TEST(Run_Wasm_Unreachable0b) {
+WASM_EXEC_TEST(Unreachable0b) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, B2(WASM_BRV(0, WASM_I8(7)), WASM_UNREACHABLE));
   CHECK_EQ(7, r.Call(0));
   CHECK_EQ(7, r.Call(1));
 }
 
-
 TEST(Build_Wasm_Unreachable1) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, WASM_UNREACHABLE);
 }
 
-
 TEST(Build_Wasm_Unreachable2) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, WASM_UNREACHABLE, WASM_UNREACHABLE);
 }
 
-
 TEST(Build_Wasm_Unreachable3) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, WASM_UNREACHABLE, WASM_UNREACHABLE, WASM_UNREACHABLE);
 }
 
-
 TEST(Build_Wasm_UnreachableIf1) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, WASM_UNREACHABLE, WASM_IF(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
 }
 
-
 TEST(Build_Wasm_UnreachableIf2) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, WASM_UNREACHABLE,
         WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_UNREACHABLE));
 }
 
-
-TEST(Run_Wasm_Unreachable_Load) {
+WASM_EXEC_TEST(Unreachable_Load) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, B2(WASM_BRV(0, WASM_GET_LOCAL(0)),
               WASM_LOAD_MEM(MachineType::Int8(), WASM_GET_LOCAL(0))));
@@ -1684,25 +1660,22 @@
   CHECK_EQ(21, r.Call(21));
 }
 
-
-TEST(Run_Wasm_Infinite_Loop_not_taken1) {
+WASM_EXEC_TEST(Infinite_Loop_not_taken1) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_INFINITE_LOOP), WASM_I8(45)));
   // Run the code, but don't go into the infinite loop.
   CHECK_EQ(45, r.Call(0));
 }
 
-
-TEST(Run_Wasm_Infinite_Loop_not_taken2) {
+WASM_EXEC_TEST(Infinite_Loop_not_taken2) {
   WasmRunner<int32_t> r(MachineType::Int32());
-  BUILD(r, B1(WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(45)),
+  BUILD(r, B1(WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_I8(45)),
                            WASM_INFINITE_LOOP)));
   // Run the code, but don't go into the infinite loop.
   CHECK_EQ(45, r.Call(1));
 }
 
-
-TEST(Run_Wasm_Infinite_Loop_not_taken2_brif) {
+WASM_EXEC_TEST(Infinite_Loop_not_taken2_brif) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r,
         B2(WASM_BRV_IF(0, WASM_I8(45), WASM_GET_LOCAL(0)), WASM_INFINITE_LOOP));
@@ -1710,10 +1683,7 @@
   CHECK_EQ(45, r.Call(1));
 }
 
-
 static void TestBuildGraphForSimpleExpression(WasmOpcode opcode) {
-  if (!WasmOpcodes::IsSupported(opcode)) return;
-
   Isolate* isolate = CcTest::InitIsolateOnce();
   Zone zone(isolate->allocator());
   HandleScope scope(isolate);
@@ -1726,20 +1696,18 @@
   FunctionSig* sig = WasmOpcodes::Signature(opcode);
 
   if (sig->parameter_count() == 1) {
-    byte code[] = {WASM_NO_LOCALS, static_cast<byte>(opcode), kExprGetLocal, 0};
-    TestBuildingGraph(&zone, &jsgraph, nullptr, sig, code,
+    byte code[] = {WASM_NO_LOCALS, kExprGetLocal, 0, static_cast<byte>(opcode)};
+    TestBuildingGraph(&zone, &jsgraph, nullptr, sig, nullptr, code,
                       code + arraysize(code));
   } else {
     CHECK_EQ(2, sig->parameter_count());
-    byte code[] = {WASM_NO_LOCALS, static_cast<byte>(opcode),
-                   kExprGetLocal,  0,
-                   kExprGetLocal,  1};
-    TestBuildingGraph(&zone, &jsgraph, nullptr, sig, code,
+    byte code[] = {WASM_NO_LOCALS,           kExprGetLocal, 0, kExprGetLocal, 1,
+                   static_cast<byte>(opcode)};
+    TestBuildingGraph(&zone, &jsgraph, nullptr, sig, nullptr, code,
                       code + arraysize(code));
   }
 }
 
-
 TEST(Build_Wasm_SimpleExprs) {
 // Test that the decoder can build a graph for all supported simple expressions.
 #define GRAPH_BUILD_TEST(name, opcode, sig) \
@@ -1750,8 +1718,7 @@
 #undef GRAPH_BUILD_TEST
 }
 
-
-TEST(Run_Wasm_Int32LoadInt8_signext) {
+WASM_EXEC_TEST(Int32LoadInt8_signext) {
   TestingModule module;
   const int kNumElems = 16;
   int8_t* memory = module.AddMemoryElems<int8_t>(kNumElems);
@@ -1765,8 +1732,7 @@
   }
 }
 
-
-TEST(Run_Wasm_Int32LoadInt8_zeroext) {
+WASM_EXEC_TEST(Int32LoadInt8_zeroext) {
   TestingModule module;
   const int kNumElems = 16;
   byte* memory = module.AddMemory(kNumElems);
@@ -1780,8 +1746,7 @@
   }
 }
 
-
-TEST(Run_Wasm_Int32LoadInt16_signext) {
+WASM_EXEC_TEST(Int32LoadInt16_signext) {
   TestingModule module;
   const int kNumBytes = 16;
   byte* memory = module.AddMemory(kNumBytes);
@@ -1796,8 +1761,7 @@
   }
 }
 
-
-TEST(Run_Wasm_Int32LoadInt16_zeroext) {
+WASM_EXEC_TEST(Int32LoadInt16_zeroext) {
   TestingModule module;
   const int kNumBytes = 16;
   byte* memory = module.AddMemory(kNumBytes);
@@ -1812,8 +1776,7 @@
   }
 }
 
-
-TEST(Run_WasmInt32Global) {
+WASM_EXEC_TEST(Int32Global) {
   TestingModule module;
   int32_t* global = module.AddGlobal<int32_t>(MachineType::Int32());
   WasmRunner<int32_t> r(&module, MachineType::Int32());
@@ -1829,8 +1792,7 @@
   }
 }
 
-
-TEST(Run_WasmInt32Globals_DontAlias) {
+WASM_EXEC_TEST(Int32Globals_DontAlias) {
   const int kNumGlobals = 3;
   TestingModule module;
   int32_t* globals[] = {module.AddGlobal<int32_t>(MachineType::Int32()),
@@ -1858,8 +1820,7 @@
   }
 }
 
-
-TEST(Run_WasmFloat32Global) {
+WASM_EXEC_TEST(Float32Global) {
   TestingModule module;
   float* global = module.AddGlobal<float>(MachineType::Float32());
   WasmRunner<int32_t> r(&module, MachineType::Int32());
@@ -1877,8 +1838,7 @@
   }
 }
 
-
-TEST(Run_WasmFloat64Global) {
+WASM_EXEC_TEST(Float64Global) {
   TestingModule module;
   double* global = module.AddGlobal<double>(MachineType::Float64());
   WasmRunner<int32_t> r(&module, MachineType::Int32());
@@ -1896,8 +1856,7 @@
   }
 }
 
-
-TEST(Run_WasmMixedGlobals) {
+WASM_EXEC_TEST(MixedGlobals) {
   TestingModule module;
   int32_t* unused = module.AddGlobal<int32_t>(MachineType::Int32());
   byte* memory = module.AddMemory(32);
@@ -1951,8 +1910,7 @@
   USE(unused);
 }
 
-
-TEST(Run_WasmCallEmpty) {
+WASM_EXEC_TEST(CallEmpty) {
   const int32_t kExpected = -414444;
   // Build the target function.
   TestSignatures sigs;
@@ -1969,8 +1927,7 @@
   CHECK_EQ(kExpected, result);
 }
 
-
-TEST(Run_WasmCallF32StackParameter) {
+WASM_EXEC_TEST(CallF32StackParameter) {
   // Build the target function.
   LocalType param_types[20];
   for (int i = 0; i < 20; i++) param_types[i] = kAstF32;
@@ -1982,8 +1939,8 @@
 
   // Build the calling function.
   WasmRunner<float> r(&module);
-  BUILD(r, WASM_CALL_FUNCTION(
-               index, WASM_F32(1.0f), WASM_F32(2.0f), WASM_F32(4.0f),
+  BUILD(r, WASM_CALL_FUNCTIONN(
+               19, index, WASM_F32(1.0f), WASM_F32(2.0f), WASM_F32(4.0f),
                WASM_F32(8.0f), WASM_F32(16.0f), WASM_F32(32.0f),
                WASM_F32(64.0f), WASM_F32(128.0f), WASM_F32(256.0f),
                WASM_F32(1.5f), WASM_F32(2.5f), WASM_F32(4.5f), WASM_F32(8.5f),
@@ -1994,8 +1951,7 @@
   CHECK_EQ(256.5f, result);
 }
 
-
-TEST(Run_WasmCallF64StackParameter) {
+WASM_EXEC_TEST(CallF64StackParameter) {
   // Build the target function.
   LocalType param_types[20];
   for (int i = 0; i < 20; i++) param_types[i] = kAstF64;
@@ -2007,19 +1963,19 @@
 
   // Build the calling function.
   WasmRunner<double> r(&module);
-  BUILD(r, WASM_CALL_FUNCTION(index, WASM_F64(1.0), WASM_F64(2.0),
-                              WASM_F64(4.0), WASM_F64(8.0), WASM_F64(16.0),
-                              WASM_F64(32.0), WASM_F64(64.0), WASM_F64(128.0),
-                              WASM_F64(256.0), WASM_F64(1.5), WASM_F64(2.5),
-                              WASM_F64(4.5), WASM_F64(8.5), WASM_F64(16.5),
-                              WASM_F64(32.5), WASM_F64(64.5), WASM_F64(128.5),
-                              WASM_F64(256.5), WASM_F64(512.5)));
+  BUILD(r, WASM_CALL_FUNCTIONN(19, index, WASM_F64(1.0), WASM_F64(2.0),
+                               WASM_F64(4.0), WASM_F64(8.0), WASM_F64(16.0),
+                               WASM_F64(32.0), WASM_F64(64.0), WASM_F64(128.0),
+                               WASM_F64(256.0), WASM_F64(1.5), WASM_F64(2.5),
+                               WASM_F64(4.5), WASM_F64(8.5), WASM_F64(16.5),
+                               WASM_F64(32.5), WASM_F64(64.5), WASM_F64(128.5),
+                               WASM_F64(256.5), WASM_F64(512.5)));
 
   float result = r.Call();
   CHECK_EQ(256.5, result);
 }
 
-TEST(Run_WasmCallVoid) {
+WASM_EXEC_TEST(CallVoid) {
   const byte kMemOffset = 8;
   const int32_t kElemNum = kMemOffset / sizeof(int32_t);
   const int32_t kExpected = -414444;
@@ -2043,8 +1999,7 @@
   CHECK_EQ(kExpected, module.raw_mem_start<int32_t>()[kElemNum]);
 }
 
-
-TEST(Run_WasmCall_Int32Add) {
+WASM_EXEC_TEST(Call_Int32Add) {
   // Build the target function.
   TestSignatures sigs;
   TestingModule module;
@@ -2054,7 +2009,7 @@
 
   // Build the caller function.
   WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
-  BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  BUILD(r, WASM_CALL_FUNCTION2(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_INT32_INPUTS(i) {
     FOR_INT32_INPUTS(j) {
@@ -2065,7 +2020,7 @@
   }
 }
 
-TEST(Run_WasmCall_Float32Sub) {
+WASM_EXEC_TEST(Call_Float32Sub) {
   TestSignatures sigs;
   TestingModule module;
   WasmFunctionCompiler t(sigs.f_ff(), &module);
@@ -2076,15 +2031,14 @@
 
   // Builder the caller function.
   WasmRunner<float> r(&module, MachineType::Float32(), MachineType::Float32());
-  BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  BUILD(r, WASM_CALL_FUNCTION2(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_FLOAT32_INPUTS(i) {
     FOR_FLOAT32_INPUTS(j) { CHECK_FLOAT_EQ(*i - *j, r.Call(*i, *j)); }
   }
 }
 
-
-TEST(Run_WasmCall_Float64Sub) {
+WASM_EXEC_TEST(Call_Float64Sub) {
   TestingModule module;
   double* memory = module.AddMemoryElems<double>(16);
   WasmRunner<int32_t> r(&module);
@@ -2118,7 +2072,6 @@
     for (size_t i = 0; i < sizeof(__buf); i++) vec.push_back(__buf[i]); \
   } while (false)
 
-
 static void Run_WasmMixedCall_N(int start) {
   const int kExpected = 6333;
   const int kElemSize = 8;
@@ -2165,23 +2118,30 @@
     // Build the calling function.
     // =========================================================================
     WasmRunner<int32_t> r(&module);
-
     std::vector<byte> code;
-    ADD_CODE(code,
-             static_cast<byte>(WasmOpcodes::LoadStoreOpcodeOf(result, true)),
-             ZERO_ALIGNMENT, ZERO_OFFSET);
-    ADD_CODE(code, WASM_ZERO);
-    ADD_CODE(code, kExprCallFunction, static_cast<byte>(index));
 
+    // Load the offset for the store.
+    ADD_CODE(code, WASM_ZERO);
+
+    // Load the arguments.
     for (int i = 0; i < num_params; i++) {
       int offset = (i + 1) * kElemSize;
       ADD_CODE(code, WASM_LOAD_MEM(memtypes[i], WASM_I8(offset)));
     }
 
+    // Call the selector function.
+    ADD_CODE(code, kExprCallFunction, static_cast<byte>(num_params),
+             static_cast<byte>(index));
+
+    // Store the result in memory.
+    ADD_CODE(code,
+             static_cast<byte>(WasmOpcodes::LoadStoreOpcodeOf(result, true)),
+             ZERO_ALIGNMENT, ZERO_OFFSET);
+
+    // Return the expected value.
     ADD_CODE(code, WASM_I32V_2(kExpected));
-    size_t end = code.size();
-    code.push_back(0);
-    r.Build(&code[0], &code[end]);
+
+    r.Build(&code[0], &code[0] + code.size());
 
     // Run the code.
     for (int t = 0; t < 10; t++) {
@@ -2199,13 +2159,12 @@
   }
 }
 
+WASM_EXEC_TEST(MixedCall_0) { Run_WasmMixedCall_N(0); }
+WASM_EXEC_TEST(MixedCall_1) { Run_WasmMixedCall_N(1); }
+WASM_EXEC_TEST(MixedCall_2) { Run_WasmMixedCall_N(2); }
+WASM_EXEC_TEST(MixedCall_3) { Run_WasmMixedCall_N(3); }
 
-TEST(Run_WasmMixedCall_0) { Run_WasmMixedCall_N(0); }
-TEST(Run_WasmMixedCall_1) { Run_WasmMixedCall_N(1); }
-TEST(Run_WasmMixedCall_2) { Run_WasmMixedCall_N(2); }
-TEST(Run_WasmMixedCall_3) { Run_WasmMixedCall_N(3); }
-
-TEST(Run_Wasm_AddCall) {
+WASM_EXEC_TEST(AddCall) {
   TestSignatures sigs;
   TestingModule module;
   WasmFunctionCompiler t1(sigs.i_ii(), &module);
@@ -2216,21 +2175,21 @@
   byte local = r.AllocateLocal(kAstI32);
   BUILD(r, B2(WASM_SET_LOCAL(local, WASM_I8(99)),
               WASM_I32_ADD(
-                  WASM_CALL_FUNCTION(t1.function_index_, WASM_GET_LOCAL(0),
-                                     WASM_GET_LOCAL(0)),
-                  WASM_CALL_FUNCTION(t1.function_index_, WASM_GET_LOCAL(1),
-                                     WASM_GET_LOCAL(local)))));
+                  WASM_CALL_FUNCTION2(t1.function_index_, WASM_GET_LOCAL(0),
+                                      WASM_GET_LOCAL(0)),
+                  WASM_CALL_FUNCTION2(t1.function_index_, WASM_GET_LOCAL(1),
+                                      WASM_GET_LOCAL(local)))));
 
   CHECK_EQ(198, r.Call(0));
   CHECK_EQ(200, r.Call(1));
   CHECK_EQ(100, r.Call(-49));
 }
 
-TEST(Run_Wasm_CountDown_expr) {
+WASM_EXEC_TEST(CountDown_expr) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, WASM_LOOP(
                3, WASM_IF(WASM_NOT(WASM_GET_LOCAL(0)),
-                          WASM_BREAKV(0, WASM_GET_LOCAL(0))),
+                          WASM_BREAKV(1, WASM_GET_LOCAL(0))),
                WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(1))),
                WASM_CONTINUE(0)));
   CHECK_EQ(0, r.Call(1));
@@ -2238,51 +2197,46 @@
   CHECK_EQ(0, r.Call(100));
 }
 
-
-TEST(Run_Wasm_ExprBlock2a) {
+WASM_EXEC_TEST(ExprBlock2a) {
   WasmRunner<int32_t> r(MachineType::Int32());
-  BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(1))), WASM_I8(1)));
+  BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_I8(1))), WASM_I8(1)));
   CHECK_EQ(1, r.Call(0));
   CHECK_EQ(1, r.Call(1));
 }
 
-
-TEST(Run_Wasm_ExprBlock2b) {
+WASM_EXEC_TEST(ExprBlock2b) {
   WasmRunner<int32_t> r(MachineType::Int32());
-  BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(1))), WASM_I8(2)));
+  BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_I8(1))), WASM_I8(2)));
   CHECK_EQ(2, r.Call(0));
   CHECK_EQ(1, r.Call(1));
 }
 
-
-TEST(Run_Wasm_ExprBlock2c) {
+WASM_EXEC_TEST(ExprBlock2c) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, B2(WASM_BRV_IF(0, WASM_I8(1), WASM_GET_LOCAL(0)), WASM_I8(1)));
   CHECK_EQ(1, r.Call(0));
   CHECK_EQ(1, r.Call(1));
 }
 
-
-TEST(Run_Wasm_ExprBlock2d) {
+WASM_EXEC_TEST(ExprBlock2d) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, B2(WASM_BRV_IF(0, WASM_I8(1), WASM_GET_LOCAL(0)), WASM_I8(2)));
   CHECK_EQ(2, r.Call(0));
   CHECK_EQ(1, r.Call(1));
 }
 
-
-TEST(Run_Wasm_ExprBlock_ManualSwitch) {
+WASM_EXEC_TEST(ExprBlock_ManualSwitch) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r, WASM_BLOCK(6, WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(1)),
-                                 WASM_BRV(0, WASM_I8(11))),
+                                 WASM_BRV(1, WASM_I8(11))),
                       WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(2)),
-                              WASM_BRV(0, WASM_I8(12))),
+                              WASM_BRV(1, WASM_I8(12))),
                       WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(3)),
-                              WASM_BRV(0, WASM_I8(13))),
+                              WASM_BRV(1, WASM_I8(13))),
                       WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(4)),
-                              WASM_BRV(0, WASM_I8(14))),
+                              WASM_BRV(1, WASM_I8(14))),
                       WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(5)),
-                              WASM_BRV(0, WASM_I8(15))),
+                              WASM_BRV(1, WASM_I8(15))),
                       WASM_I8(99)));
   CHECK_EQ(99, r.Call(0));
   CHECK_EQ(11, r.Call(1));
@@ -2293,8 +2247,7 @@
   CHECK_EQ(99, r.Call(6));
 }
 
-
-TEST(Run_Wasm_ExprBlock_ManualSwitch_brif) {
+WASM_EXEC_TEST(ExprBlock_ManualSwitch_brif) {
   WasmRunner<int32_t> r(MachineType::Int32());
   BUILD(r,
         WASM_BLOCK(6, WASM_BRV_IF(0, WASM_I8(11),
@@ -2317,8 +2270,7 @@
   CHECK_EQ(99, r.Call(6));
 }
 
-
-TEST(Run_Wasm_nested_ifs) {
+WASM_EXEC_TEST(nested_ifs) {
   WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
 
   BUILD(r, WASM_IF_ELSE(
@@ -2326,36 +2278,32 @@
                WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_I8(11), WASM_I8(12)),
                WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_I8(13), WASM_I8(14))));
 
-
   CHECK_EQ(11, r.Call(1, 1));
   CHECK_EQ(12, r.Call(1, 0));
   CHECK_EQ(13, r.Call(0, 1));
   CHECK_EQ(14, r.Call(0, 0));
 }
 
-
-TEST(Run_Wasm_ExprBlock_if) {
+WASM_EXEC_TEST(ExprBlock_if) {
   WasmRunner<int32_t> r(MachineType::Int32());
 
   BUILD(r, B1(WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(11)),
-                           WASM_BRV(0, WASM_I8(14)))));
+                           WASM_BRV(1, WASM_I8(14)))));
 
   CHECK_EQ(11, r.Call(1));
   CHECK_EQ(14, r.Call(0));
 }
 
-
-TEST(Run_Wasm_ExprBlock_nested_ifs) {
+WASM_EXEC_TEST(ExprBlock_nested_ifs) {
   WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
 
   BUILD(r, WASM_BLOCK(
                1, WASM_IF_ELSE(
                       WASM_GET_LOCAL(0),
                       WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(0, WASM_I8(11)),
-                                   WASM_BRV(0, WASM_I8(12))),
+                                   WASM_BRV(1, WASM_I8(12))),
                       WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(0, WASM_I8(13)),
-                                   WASM_BRV(0, WASM_I8(14))))));
-
+                                   WASM_BRV(1, WASM_I8(14))))));
 
   CHECK_EQ(11, r.Call(1, 1));
   CHECK_EQ(12, r.Call(1, 0));
@@ -2363,18 +2311,16 @@
   CHECK_EQ(14, r.Call(0, 0));
 }
 
-
-TEST(Run_Wasm_ExprLoop_nested_ifs) {
+WASM_EXEC_TEST(ExprLoop_nested_ifs) {
   WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
 
   BUILD(r, WASM_LOOP(
                1, WASM_IF_ELSE(
                       WASM_GET_LOCAL(0),
                       WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(1, WASM_I8(11)),
-                                   WASM_BRV(1, WASM_I8(12))),
+                                   WASM_BRV(3, WASM_I8(12))),
                       WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(1, WASM_I8(13)),
-                                   WASM_BRV(1, WASM_I8(14))))));
-
+                                   WASM_BRV(3, WASM_I8(14))))));
 
   CHECK_EQ(11, r.Call(1, 1));
   CHECK_EQ(12, r.Call(1, 0));
@@ -2382,8 +2328,7 @@
   CHECK_EQ(14, r.Call(0, 0));
 }
 
-
-TEST(Run_Wasm_SimpleCallIndirect) {
+WASM_EXEC_TEST(SimpleCallIndirect) {
   TestSignatures sigs;
   TestingModule module;
 
@@ -2407,15 +2352,14 @@
 
   // Builder the caller function.
   WasmRunner<int32_t> r(&module, MachineType::Int32());
-  BUILD(r, WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(0), WASM_I8(66), WASM_I8(22)));
+  BUILD(r, WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(0), WASM_I8(66), WASM_I8(22)));
 
   CHECK_EQ(88, r.Call(0));
   CHECK_EQ(44, r.Call(1));
   CHECK_TRAP(r.Call(2));
 }
 
-
-TEST(Run_Wasm_MultipleCallIndirect) {
+WASM_EXEC_TEST(MultipleCallIndirect) {
   TestSignatures sigs;
   TestingModule module;
 
@@ -2440,11 +2384,11 @@
   // Builder the caller function.
   WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32(),
                         MachineType::Int32());
-  BUILD(r,
-        WASM_I32_ADD(WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1),
-                                        WASM_GET_LOCAL(2)),
-                     WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(1), WASM_GET_LOCAL(2),
-                                        WASM_GET_LOCAL(0))));
+  BUILD(r, WASM_I32_ADD(
+               WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1),
+                                   WASM_GET_LOCAL(2)),
+               WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(1), WASM_GET_LOCAL(2),
+                                   WASM_GET_LOCAL(0))));
 
   CHECK_EQ(5, r.Call(0, 1, 2));
   CHECK_EQ(19, r.Call(0, 1, 9));
@@ -2457,7 +2401,7 @@
   CHECK_TRAP(r.Call(2, 1, 0));
 }
 
-TEST(Run_Wasm_CallIndirect_NoTable) {
+WASM_EXEC_TEST(CallIndirect_NoTable) {
   TestSignatures sigs;
   TestingModule module;
 
@@ -2472,70 +2416,70 @@
 
   // Builder the caller function.
   WasmRunner<int32_t> r(&module, MachineType::Int32());
-  BUILD(r, WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(0), WASM_I8(66), WASM_I8(22)));
+  BUILD(r, WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(0), WASM_I8(66), WASM_I8(22)));
 
   CHECK_TRAP(r.Call(0));
   CHECK_TRAP(r.Call(1));
   CHECK_TRAP(r.Call(2));
 }
 
-TEST(Run_Wasm_F32Floor) {
+WASM_EXEC_TEST(F32Floor) {
   WasmRunner<float> r(MachineType::Float32());
   BUILD(r, WASM_F32_FLOOR(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(floorf(*i), r.Call(*i)); }
 }
 
-TEST(Run_Wasm_F32Ceil) {
+WASM_EXEC_TEST(F32Ceil) {
   WasmRunner<float> r(MachineType::Float32());
   BUILD(r, WASM_F32_CEIL(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(ceilf(*i), r.Call(*i)); }
 }
 
-TEST(Run_Wasm_F32Trunc) {
+WASM_EXEC_TEST(F32Trunc) {
   WasmRunner<float> r(MachineType::Float32());
   BUILD(r, WASM_F32_TRUNC(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(truncf(*i), r.Call(*i)); }
 }
 
-TEST(Run_Wasm_F32NearestInt) {
+WASM_EXEC_TEST(F32NearestInt) {
   WasmRunner<float> r(MachineType::Float32());
   BUILD(r, WASM_F32_NEARESTINT(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(nearbyintf(*i), r.Call(*i)); }
 }
 
-TEST(Run_Wasm_F64Floor) {
+WASM_EXEC_TEST(F64Floor) {
   WasmRunner<double> r(MachineType::Float64());
   BUILD(r, WASM_F64_FLOOR(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(floor(*i), r.Call(*i)); }
 }
 
-TEST(Run_Wasm_F64Ceil) {
+WASM_EXEC_TEST(F64Ceil) {
   WasmRunner<double> r(MachineType::Float64());
   BUILD(r, WASM_F64_CEIL(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ceil(*i), r.Call(*i)); }
 }
 
-TEST(Run_Wasm_F64Trunc) {
+WASM_EXEC_TEST(F64Trunc) {
   WasmRunner<double> r(MachineType::Float64());
   BUILD(r, WASM_F64_TRUNC(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(trunc(*i), r.Call(*i)); }
 }
 
-TEST(Run_Wasm_F64NearestInt) {
+WASM_EXEC_TEST(F64NearestInt) {
   WasmRunner<double> r(MachineType::Float64());
   BUILD(r, WASM_F64_NEARESTINT(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(nearbyint(*i), r.Call(*i)); }
 }
 
-TEST(Run_Wasm_F32Min) {
+WASM_EXEC_TEST(F32Min) {
   WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());
   BUILD(r, WASM_F32_MIN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
@@ -2558,8 +2502,7 @@
   }
 }
 
-
-TEST(Run_Wasm_F64Min) {
+WASM_EXEC_TEST(F64Min) {
   WasmRunner<double> r(MachineType::Float64(), MachineType::Float64());
   BUILD(r, WASM_F64_MIN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
@@ -2582,8 +2525,7 @@
   }
 }
 
-
-TEST(Run_Wasm_F32Max) {
+WASM_EXEC_TEST(F32Max) {
   WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());
   BUILD(r, WASM_F32_MAX(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
@@ -2606,8 +2548,7 @@
   }
 }
 
-
-TEST(Run_Wasm_F64Max) {
+WASM_EXEC_TEST(F64Max) {
   WasmRunner<double> r(MachineType::Float64(), MachineType::Float64());
   BUILD(r, WASM_F64_MAX(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
@@ -2630,11 +2571,10 @@
   }
 }
 
-// TODO(ahaas): Fix on arm and mips and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS && \
-    !V8_TARGET_ARCH_MIPS64
+// TODO(ahaas): Fix on mips and reenable.
+#if !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_MIPS64
 
-TEST(Run_Wasm_F32Min_Snan) {
+WASM_EXEC_TEST(F32Min_Snan) {
   // Test that the instruction does not return a signalling NaN.
   {
     WasmRunner<float> r;
@@ -2650,7 +2590,7 @@
   }
 }
 
-TEST(Run_Wasm_F32Max_Snan) {
+WASM_EXEC_TEST(F32Max_Snan) {
   // Test that the instruction does not return a signalling NaN.
   {
     WasmRunner<float> r;
@@ -2666,7 +2606,7 @@
   }
 }
 
-TEST(Run_Wasm_F64Min_Snan) {
+WASM_EXEC_TEST(F64Min_Snan) {
   // Test that the instruction does not return a signalling NaN.
   {
     WasmRunner<double> r;
@@ -2682,7 +2622,7 @@
   }
 }
 
-TEST(Run_Wasm_F64Max_Snan) {
+WASM_EXEC_TEST(F64Max_Snan) {
   // Test that the instruction does not return a signalling NaN.
   {
     WasmRunner<double> r;
@@ -2700,7 +2640,7 @@
 
 #endif
 
-TEST(Run_Wasm_I32SConvertF32) {
+WASM_EXEC_TEST(I32SConvertF32) {
   WasmRunner<int32_t> r(MachineType::Float32());
   BUILD(r, WASM_I32_SCONVERT_F32(WASM_GET_LOCAL(0)));
 
@@ -2714,8 +2654,7 @@
   }
 }
 
-
-TEST(Run_Wasm_I32SConvertF64) {
+WASM_EXEC_TEST(I32SConvertF64) {
   WasmRunner<int32_t> r(MachineType::Float64());
   BUILD(r, WASM_I32_SCONVERT_F64(WASM_GET_LOCAL(0)));
 
@@ -2729,8 +2668,7 @@
   }
 }
 
-
-TEST(Run_Wasm_I32UConvertF32) {
+WASM_EXEC_TEST(I32UConvertF32) {
   WasmRunner<uint32_t> r(MachineType::Float32());
   BUILD(r, WASM_I32_UCONVERT_F32(WASM_GET_LOCAL(0)));
 
@@ -2743,8 +2681,7 @@
   }
 }
 
-
-TEST(Run_Wasm_I32UConvertF64) {
+WASM_EXEC_TEST(I32UConvertF64) {
   WasmRunner<uint32_t> r(MachineType::Float64());
   BUILD(r, WASM_I32_UCONVERT_F64(WASM_GET_LOCAL(0)));
 
@@ -2757,7 +2694,7 @@
   }
 }
 
-TEST(Run_Wasm_F64CopySign) {
+WASM_EXEC_TEST(F64CopySign) {
   WasmRunner<double> r(MachineType::Float64(), MachineType::Float64());
   BUILD(r, WASM_F64_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
@@ -2766,8 +2703,7 @@
   }
 }
 
-
-TEST(Run_Wasm_F32CopySign) {
+WASM_EXEC_TEST(F32CopySign) {
   WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());
   BUILD(r, WASM_F32_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
@@ -2794,32 +2730,28 @@
     WasmFunctionCompiler t(sig, &module);
 
     std::vector<byte> code;
-    ADD_CODE(code, kExprCallIndirect, 1);
     ADD_CODE(code, kExprI8Const, 0);
     for (byte p = 0; p < num_params; p++) {
       ADD_CODE(code, kExprGetLocal, p);
     }
+    ADD_CODE(code, kExprCallIndirect, static_cast<byte>(num_params), 1);
 
     t.Build(&code[0], &code[0] + code.size());
     t.Compile();
   }
 }
 
-
 TEST(Compile_Wasm_CallIndirect_Many_i32) { CompileCallIndirectMany(kAstI32); }
 
-
 #if WASM_64
 TEST(Compile_Wasm_CallIndirect_Many_i64) { CompileCallIndirectMany(kAstI64); }
 #endif
 
-
 TEST(Compile_Wasm_CallIndirect_Many_f32) { CompileCallIndirectMany(kAstF32); }
 
-
 TEST(Compile_Wasm_CallIndirect_Many_f64) { CompileCallIndirectMany(kAstF64); }
 
-TEST(Run_WASM_Int32RemS_dead) {
+WASM_EXEC_TEST(Int32RemS_dead) {
   WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
   BUILD(r, WASM_I32_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)), WASM_ZERO);
   const int32_t kMin = std::numeric_limits<int32_t>::min();
diff --git a/test/cctest/wasm/test-wasm-function-name-table.cc b/test/cctest/wasm/test-wasm-function-name-table.cc
new file mode 100644
index 0000000..2f1e251
--- /dev/null
+++ b/test/cctest/wasm/test-wasm-function-name-table.cc
@@ -0,0 +1,110 @@
+// 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/wasm-function-name-table.h"
+#include "src/wasm/wasm-module.h"
+
+#include "test/cctest/cctest.h"
+
+using namespace v8::internal;
+using namespace v8::internal::wasm;
+
+namespace {
+
+#define CHECK_STREQ(exp, found)                                                \
+  do {                                                                         \
+    Vector<const char> exp_ = (exp);                                           \
+    Vector<const char> found_ = (found);                                       \
+    if (V8_UNLIKELY(exp_.length() != found_.length() ||                        \
+                    memcmp(exp_.start(), found_.start(), exp_.length()))) {    \
+      V8_Fatal(__FILE__, __LINE__,                                             \
+               "Check failed: (%s) != (%s) ('%.*s' vs '%.*s').", #exp, #found, \
+               exp_.length(), exp_.start(), found_.length(), found_.start());  \
+    }                                                                          \
+  } while (0)
+
+void testFunctionNameTable(Vector<Vector<const char>> names) {
+  Isolate *isolate = CcTest::InitIsolateOnce();
+  HandleAndZoneScope scope;
+
+  WasmModule module;
+  std::vector<char> all_names;
+
+  uint32_t func_index = 0;
+  for (Vector<const char> name : names) {
+    size_t name_offset = all_names.size();
+    all_names.insert(all_names.end(), name.start(),
+                     name.start() + name.length());
+    // Make every second function name null-terminated.
+    if (func_index % 2) all_names.push_back('\0');
+    module.functions.push_back(
+        {nullptr, 0, 0, static_cast<uint32_t>(name_offset),
+         static_cast<uint32_t>(name.length()), 0, 0, false});
+    ++func_index;
+  }
+
+  module.module_start = reinterpret_cast<byte *>(all_names.data());
+  module.module_end = module.module_start + all_names.size();
+
+  Handle<Object> wasm_function_name_table =
+      BuildFunctionNamesTable(isolate, &module);
+  CHECK(wasm_function_name_table->IsByteArray());
+
+  func_index = 0;
+  for (Vector<const char> name : names) {
+    Handle<Object> string_obj = GetWasmFunctionNameFromTable(
+        Handle<ByteArray>::cast(wasm_function_name_table), func_index);
+    CHECK(!string_obj.is_null());
+    CHECK(string_obj->IsString());
+    Handle<String> string = Handle<String>::cast(string_obj);
+    CHECK(string->IsUtf8EqualTo(name));
+    ++func_index;
+  }
+}
+
+void testFunctionNameTable(Vector<const char *> names) {
+  std::vector<Vector<const char>> names_vec;
+  for (const char *name : names) names_vec.push_back(CStrVector(name));
+  testFunctionNameTable(Vector<Vector<const char>>(
+      names_vec.data(), static_cast<int>(names_vec.size())));
+}
+
+}  // namespace
+
+TEST(NoFunctions) { testFunctionNameTable(Vector<Vector<const char>>()); }
+
+TEST(OneFunctions) {
+  const char *names[] = {"foo"};
+  testFunctionNameTable(ArrayVector(names));
+}
+
+TEST(ThreeFunctions) {
+  const char *names[] = {"foo", "bar", "baz"};
+  testFunctionNameTable(ArrayVector(names));
+}
+
+TEST(OneUnnamedFunction) {
+  const char *names[] = {""};
+  testFunctionNameTable(ArrayVector(names));
+}
+
+TEST(UnnamedFirstFunction) {
+  const char *names[] = {"", "bar", "baz"};
+  testFunctionNameTable(ArrayVector(names));
+}
+
+TEST(UnnamedLastFunction) {
+  const char *names[] = {"bar", "baz", ""};
+  testFunctionNameTable(ArrayVector(names));
+}
+
+TEST(ThreeUnnamedFunctions) {
+  const char *names[] = {"", "", ""};
+  testFunctionNameTable(ArrayVector(names));
+}
+
+TEST(UTF8Names) {
+  const char *names[] = {"↱fun↰", "↺", "alpha:α beta:β"};
+  testFunctionNameTable(ArrayVector(names));
+}
diff --git a/test/cctest/wasm/test-wasm-stack.cc b/test/cctest/wasm/test-wasm-stack.cc
new file mode 100644
index 0000000..b6cd674
--- /dev/null
+++ b/test/cctest/wasm/test-wasm-stack.cc
@@ -0,0 +1,166 @@
+// 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/wasm-macro-gen.h"
+
+#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/value-helper.h"
+#include "test/cctest/wasm/test-signatures.h"
+#include "test/cctest/wasm/wasm-run-utils.h"
+
+using namespace v8::base;
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+using namespace v8::internal::wasm;
+
+using v8::Local;
+using v8::Utils;
+
+namespace {
+
+#define CHECK_CSTREQ(exp, found)                                           \
+  do {                                                                     \
+    const char* exp_ = (exp);                                              \
+    const char* found_ = (found);                                          \
+    DCHECK_NOT_NULL(exp);                                                  \
+    if (V8_UNLIKELY(found_ == nullptr || strcmp(exp_, found_) != 0)) {     \
+      V8_Fatal(__FILE__, __LINE__,                                         \
+               "Check failed: (%s) != (%s) ('%s' vs '%s').", #exp, #found, \
+               exp_, found_ ? found_ : "<null>");                          \
+    }                                                                      \
+  } while (0)
+
+void PrintStackTrace(v8::Local<v8::StackTrace> stack) {
+  printf("Stack Trace (length %d):\n", stack->GetFrameCount());
+  for (int i = 0, e = stack->GetFrameCount(); i != e; ++i) {
+    v8::Local<v8::StackFrame> frame = stack->GetFrame(i);
+    v8::Local<v8::String> script = frame->GetScriptName();
+    v8::Local<v8::String> func = frame->GetFunctionName();
+    printf("[%d] (%s) %s:%d:%d\n", i,
+           script.IsEmpty() ? "<null>" : *v8::String::Utf8Value(script),
+           func.IsEmpty() ? "<null>" : *v8::String::Utf8Value(func),
+           frame->GetLineNumber(), frame->GetColumn());
+  }
+}
+
+struct ExceptionInfo {
+  const char* func_name;
+  int line_nr;
+  int column;
+};
+
+template <int N>
+void CheckExceptionInfos(Isolate* isolate, Handle<Object> exc,
+                         const ExceptionInfo (&excInfos)[N]) {
+  // Check that it's indeed an Error object.
+  CHECK(Object::IsErrorObject(isolate, exc));
+
+  // Extract stack frame from the exception.
+  Local<v8::Value> localExc = Utils::ToLocal(exc);
+  v8::Local<v8::StackTrace> stack = v8::Exception::GetStackTrace(localExc);
+  PrintStackTrace(stack);
+  CHECK(!stack.IsEmpty());
+  CHECK_EQ(N, stack->GetFrameCount());
+
+  for (int frameNr = 0; frameNr < N; ++frameNr) {
+    v8::Local<v8::StackFrame> frame = stack->GetFrame(frameNr);
+    v8::String::Utf8Value funName(frame->GetFunctionName());
+    CHECK_CSTREQ(excInfos[frameNr].func_name, *funName);
+    CHECK_EQ(excInfos[frameNr].line_nr, frame->GetLineNumber());
+    CHECK_EQ(excInfos[frameNr].column, frame->GetColumn());
+  }
+}
+
+}  // namespace
+
+// Call from JS to WASM to JS and throw an Error from JS.
+TEST(CollectDetailedWasmStack_ExplicitThrowFromJs) {
+  TestSignatures sigs;
+  TestingModule module;
+
+  // Initialize WasmFunctionCompiler first, since it sets up the HandleScope.
+  WasmFunctionCompiler comp1(sigs.v_v(), &module);
+
+  uint32_t js_throwing_index = module.AddJsFunction(
+      sigs.v_v(),
+      "(function js() {\n function a() {\n throw new Error(); };\n a(); })");
+
+  // Add a nop such that we don't always get position 1.
+  BUILD(comp1, WASM_NOP, WASM_CALL_FUNCTION0(js_throwing_index));
+  uint32_t wasm_index = comp1.CompileAndAdd();
+
+  WasmFunctionCompiler comp2(sigs.v_v(), &module);
+  BUILD(comp2, WASM_CALL_FUNCTION0(wasm_index));
+  uint32_t wasm_index_2 = comp2.CompileAndAdd();
+
+  Handle<JSFunction> js_wasm_wrapper = module.WrapCode(wasm_index_2);
+
+  Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast(
+      v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
+          CompileRun("(function callFn(fn) { fn(); })"))));
+
+  Isolate* isolate = js_wasm_wrapper->GetIsolate();
+  isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
+                                                     v8::StackTrace::kOverview);
+  Handle<Object> global(isolate->context()->global_object(), isolate);
+  MaybeHandle<Object> maybe_exc;
+  Handle<Object> args[] = {js_wasm_wrapper};
+  MaybeHandle<Object> returnObjMaybe =
+      Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc);
+  CHECK(returnObjMaybe.is_null());
+
+  // Line number is 1-based, with 0 == kNoLineNumberInfo.
+  ExceptionInfo expected_exceptions[] = {
+      {"a", 3, 8},                                    // -
+      {"js", 4, 2},                                   // -
+      {"<WASM>", static_cast<int>(wasm_index), 2},    // -
+      {"<WASM>", static_cast<int>(wasm_index_2), 1},  // -
+      {"callFn", 1, 24}                               // -
+  };
+  CheckExceptionInfos(isolate, maybe_exc.ToHandleChecked(),
+                      expected_exceptions);
+}
+
+// Trigger a trap in WASM, stack should be JS -> WASM -> WASM.
+TEST(CollectDetailedWasmStack_WasmError) {
+  TestSignatures sigs;
+  TestingModule module;
+
+  WasmFunctionCompiler comp1(sigs.i_v(), &module,
+                             ArrayVector("exec_unreachable"));
+  // Set the execution context, such that a runtime error can be thrown.
+  comp1.SetModuleContext();
+  BUILD(comp1, WASM_UNREACHABLE);
+  uint32_t wasm_index = comp1.CompileAndAdd();
+
+  WasmFunctionCompiler comp2(sigs.i_v(), &module,
+                             ArrayVector("call_exec_unreachable"));
+  BUILD(comp2, WASM_CALL_FUNCTION0(wasm_index));
+  uint32_t wasm_index_2 = comp2.CompileAndAdd();
+
+  Handle<JSFunction> js_wasm_wrapper = module.WrapCode(wasm_index_2);
+
+  Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast(
+      v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
+          CompileRun("(function callFn(fn) { fn(); })"))));
+
+  Isolate* isolate = js_wasm_wrapper->GetIsolate();
+  isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
+                                                     v8::StackTrace::kOverview);
+  Handle<Object> global(isolate->context()->global_object(), isolate);
+  MaybeHandle<Object> maybe_exc;
+  Handle<Object> args[] = {js_wasm_wrapper};
+  MaybeHandle<Object> maybe_return_obj =
+      Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc);
+  CHECK(maybe_return_obj.is_null());
+
+  // Line number is 1-based, with 0 == kNoLineNumberInfo.
+  ExceptionInfo expected_exceptions[] = {
+      {"<WASM>", static_cast<int>(wasm_index), 1},    // -
+      {"<WASM>", static_cast<int>(wasm_index_2), 1},  // -
+      {"callFn", 1, 24}                               //-
+  };
+  CheckExceptionInfos(isolate, maybe_exc.ToHandleChecked(),
+                      expected_exceptions);
+}
diff --git a/test/cctest/wasm/test-wasm-trap-position.cc b/test/cctest/wasm/test-wasm-trap-position.cc
new file mode 100644
index 0000000..13f2929
--- /dev/null
+++ b/test/cctest/wasm/test-wasm-trap-position.cc
@@ -0,0 +1,140 @@
+// 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/wasm-macro-gen.h"
+
+#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/value-helper.h"
+#include "test/cctest/wasm/test-signatures.h"
+#include "test/cctest/wasm/wasm-run-utils.h"
+
+using namespace v8::base;
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+using namespace v8::internal::wasm;
+
+using v8::Local;
+using v8::Utils;
+
+namespace {
+
+#define CHECK_CSTREQ(exp, found)                                           \
+  do {                                                                     \
+    const char* exp_ = (exp);                                              \
+    const char* found_ = (found);                                          \
+    DCHECK_NOT_NULL(exp);                                                  \
+    if (V8_UNLIKELY(found_ == nullptr || strcmp(exp_, found_) != 0)) {     \
+      V8_Fatal(__FILE__, __LINE__,                                         \
+               "Check failed: (%s) != (%s) ('%s' vs '%s').", #exp, #found, \
+               exp_, found_ ? found_ : "<null>");                          \
+    }                                                                      \
+  } while (0)
+
+struct ExceptionInfo {
+  const char* func_name;
+  int line_nr;
+  int column;
+};
+
+template <int N>
+void CheckExceptionInfos(Isolate* isolate, Handle<Object> exc,
+                         const ExceptionInfo (&excInfos)[N]) {
+  // Check that it's indeed an Error object.
+  CHECK(Object::IsErrorObject(isolate, exc));
+
+  // Extract stack frame from the exception.
+  Local<v8::Value> localExc = Utils::ToLocal(exc);
+  v8::Local<v8::StackTrace> stack = v8::Exception::GetStackTrace(localExc);
+  CHECK(!stack.IsEmpty());
+  CHECK_EQ(N, stack->GetFrameCount());
+
+  for (int frameNr = 0; frameNr < N; ++frameNr) {
+    v8::Local<v8::StackFrame> frame = stack->GetFrame(frameNr);
+    v8::String::Utf8Value funName(frame->GetFunctionName());
+    CHECK_CSTREQ(excInfos[frameNr].func_name, *funName);
+    CHECK_EQ(excInfos[frameNr].line_nr, frame->GetLineNumber());
+    CHECK_EQ(excInfos[frameNr].column, frame->GetColumn());
+  }
+}
+
+}  // namespace
+
+// Trigger a trap for executing unreachable.
+TEST(Unreachable) {
+  TestSignatures sigs;
+  TestingModule module;
+
+  WasmFunctionCompiler comp1(sigs.v_v(), &module,
+                             ArrayVector("exec_unreachable"));
+  // Set the execution context, such that a runtime error can be thrown.
+  comp1.SetModuleContext();
+  BUILD(comp1, WASM_UNREACHABLE);
+  uint32_t wasm_index = comp1.CompileAndAdd();
+
+  Handle<JSFunction> js_wasm_wrapper = module.WrapCode(wasm_index);
+
+  Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast(
+      v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
+          CompileRun("(function callFn(fn) { fn(); })"))));
+
+  Isolate* isolate = js_wasm_wrapper->GetIsolate();
+  isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
+                                                     v8::StackTrace::kOverview);
+  Handle<Object> global(isolate->context()->global_object(), isolate);
+  MaybeHandle<Object> maybe_exc;
+  Handle<Object> args[] = {js_wasm_wrapper};
+  MaybeHandle<Object> returnObjMaybe =
+      Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc);
+  CHECK(returnObjMaybe.is_null());
+
+  ExceptionInfo expected_exceptions[] = {
+      {"<WASM>", static_cast<int>(wasm_index), 1},  // --
+      {"callFn", 1, 24}                             // --
+  };
+  CheckExceptionInfos(isolate, maybe_exc.ToHandleChecked(),
+                      expected_exceptions);
+}
+
+// Trigger a trap for loading from out-of-bounds.
+TEST(IllegalLoad) {
+  TestSignatures sigs;
+  TestingModule module;
+
+  WasmFunctionCompiler comp1(sigs.v_v(), &module, ArrayVector("mem_oob"));
+  // Set the execution context, such that a runtime error can be thrown.
+  comp1.SetModuleContext();
+  BUILD(comp1, WASM_IF(WASM_ONE,
+                       WASM_LOAD_MEM(MachineType::Int32(), WASM_I32V_1(-3))));
+  uint32_t wasm_index = comp1.CompileAndAdd();
+
+  WasmFunctionCompiler comp2(sigs.v_v(), &module, ArrayVector("call_mem_oob"));
+  // Insert a NOP such that the position of the call is not one.
+  BUILD(comp2, WASM_NOP, WASM_CALL_FUNCTION0(wasm_index));
+  uint32_t wasm_index_2 = comp2.CompileAndAdd();
+
+  Handle<JSFunction> js_wasm_wrapper = module.WrapCode(wasm_index_2);
+
+  Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast(
+      v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
+          CompileRun("(function callFn(fn) { fn(); })"))));
+
+  Isolate* isolate = js_wasm_wrapper->GetIsolate();
+  isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
+                                                     v8::StackTrace::kOverview);
+  Handle<Object> global(isolate->context()->global_object(), isolate);
+  MaybeHandle<Object> maybe_exc;
+  Handle<Object> args[] = {js_wasm_wrapper};
+  MaybeHandle<Object> returnObjMaybe =
+      Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc);
+  CHECK(returnObjMaybe.is_null());
+
+  // Line number is 1-based, with 0 == kNoLineNumberInfo.
+  ExceptionInfo expected_exceptions[] = {
+      {"<WASM>", static_cast<int>(wasm_index), 6},    // --
+      {"<WASM>", static_cast<int>(wasm_index_2), 2},  // --
+      {"callFn", 1, 24}                               // --
+  };
+  CheckExceptionInfos(isolate, maybe_exc.ToHandleChecked(),
+                      expected_exceptions);
+}
diff --git a/test/cctest/wasm/wasm-run-utils.h b/test/cctest/wasm/wasm-run-utils.h
index 1e85f46..a92c9ff 100644
--- a/test/cctest/wasm/wasm-run-utils.h
+++ b/test/cctest/wasm/wasm-run-utils.h
@@ -17,9 +17,11 @@
 #include "src/compiler/node.h"
 #include "src/compiler/pipeline.h"
 #include "src/compiler/wasm-compiler.h"
+#include "src/compiler/zone-pool.h"
 
 #include "src/wasm/ast-decoder.h"
 #include "src/wasm/wasm-js.h"
+#include "src/wasm/wasm-macro-gen.h"
 #include "src/wasm/wasm-module.h"
 #include "src/wasm/wasm-opcodes.h"
 
@@ -159,20 +161,43 @@
     rng.NextBytes(raw, end - raw);
   }
 
-  int AddFunction(FunctionSig* sig, Handle<Code> code) {
+  uint32_t AddFunction(FunctionSig* sig, Handle<Code> code) {
     if (module->functions.size() == 0) {
       // TODO(titzer): Reserving space here to avoid the underlying WasmFunction
       // structs from moving.
       module->functions.reserve(kMaxFunctions);
     }
     uint32_t index = static_cast<uint32_t>(module->functions.size());
-    module->functions.push_back(
-        {sig, index, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, false});
+    module->functions.push_back({sig, index, 0, 0, 0, 0, 0, false});
     instance->function_code.push_back(code);
     DCHECK_LT(index, kMaxFunctions);  // limited for testing.
     return index;
   }
 
+  uint32_t AddJsFunction(FunctionSig* sig, const char* source) {
+    Handle<JSFunction> jsfunc = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
+        *v8::Local<v8::Function>::Cast(CompileRun(source))));
+    uint32_t index = AddFunction(sig, Handle<Code>::null());
+    Isolate* isolate = module->shared_isolate;
+    WasmName module_name = ArrayVector("test");
+    WasmName function_name;
+    Handle<Code> code = CompileWasmToJSWrapper(isolate, this, jsfunc, sig,
+                                               module_name, function_name);
+    instance->function_code[index] = code;
+    return index;
+  }
+
+  Handle<JSFunction> WrapCode(uint32_t index) {
+    Isolate* isolate = module->shared_isolate;
+    // Wrap the code so it can be called as a JS function.
+    Handle<String> name = isolate->factory()->NewStringFromStaticChars("main");
+    Handle<JSObject> module_object = Handle<JSObject>(0, isolate);
+    Handle<Code> code = instance->function_code[index];
+    WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
+    return compiler::CompileJSToWasmWrapper(isolate, this, name, code,
+                                            module_object, index);
+  }
+
   void SetFunctionCode(uint32_t index, Handle<Code> code) {
     instance->function_code[index] = code;
   }
@@ -218,9 +243,10 @@
 };
 
 inline void TestBuildingGraph(Zone* zone, JSGraph* jsgraph, ModuleEnv* module,
-                              FunctionSig* sig, const byte* start,
-                              const byte* end) {
-  compiler::WasmGraphBuilder builder(zone, jsgraph, sig);
+                              FunctionSig* sig,
+                              SourcePositionTable* source_position_table,
+                              const byte* start, const byte* end) {
+  compiler::WasmGraphBuilder builder(zone, jsgraph, sig, source_position_table);
   TreeResult result =
       BuildTFGraph(zone->allocator(), &builder, module, sig, start, end);
   if (result.failed()) {
@@ -356,7 +382,7 @@
         r.LowerGraph();
       }
 
-      CompilationInfo info("testing", isolate, graph()->zone());
+      CompilationInfo info(ArrayVector("testing"), isolate, graph()->zone());
       code_ =
           Pipeline::GenerateCodeForTesting(&info, descriptor, graph(), nullptr);
       CHECK(!code_.is_null());
@@ -386,13 +412,18 @@
 class WasmFunctionCompiler : public HandleAndZoneScope,
                              private GraphAndBuilders {
  public:
-  explicit WasmFunctionCompiler(FunctionSig* sig, TestingModule* module)
+  explicit WasmFunctionCompiler(
+      FunctionSig* sig, TestingModule* module,
+      Vector<const char> debug_name = ArrayVector("<WASM UNNAMED>"))
       : GraphAndBuilders(main_zone()),
         jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
                 nullptr, this->machine()),
         sig(sig),
         descriptor_(nullptr),
-        testing_module_(module) {
+        testing_module_(module),
+        debug_name_(debug_name),
+        local_decls(main_zone(), sig),
+        source_position_table_(this->graph()) {
     if (module) {
       // Get a new function from the testing module.
       function_ = nullptr;
@@ -414,9 +445,11 @@
   // The call descriptor is initialized when the function is compiled.
   CallDescriptor* descriptor_;
   TestingModule* testing_module_;
+  Vector<const char> debug_name_;
   WasmFunction* function_;
   int function_index_;
   LocalDeclEncoder local_decls;
+  SourcePositionTable source_position_table_;
 
   Isolate* isolate() { return main_isolate(); }
   Graph* graph() const { return main_graph_; }
@@ -433,12 +466,13 @@
   void Build(const byte* start, const byte* end) {
     // Build the TurboFan graph.
     local_decls.Prepend(&start, &end);
-    TestBuildingGraph(main_zone(), &jsgraph, testing_module_, sig, start, end);
+    TestBuildingGraph(main_zone(), &jsgraph, testing_module_, sig,
+                      &source_position_table_, start, end);
     delete[] start;
   }
 
   byte AllocateLocal(LocalType type) {
-    uint32_t index = local_decls.AddLocals(1, type, sig);
+    uint32_t index = local_decls.AddLocals(1, type);
     byte result = static_cast<byte>(index);
     DCHECK_EQ(index, result);
     return result;
@@ -450,17 +484,34 @@
     if (kPointerSize == 4) {
       desc = testing_module_->GetI32WasmCallDescriptor(this->zone(), desc);
     }
-    CompilationInfo info("wasm compile", this->isolate(), this->zone());
-    Handle<Code> result =
-        Pipeline::GenerateCodeForTesting(&info, desc, this->graph());
+    CompilationInfo info(debug_name_, this->isolate(), this->zone(),
+                         Code::ComputeFlags(Code::WASM_FUNCTION));
+    v8::base::SmartPointer<CompilationJob> job(Pipeline::NewWasmCompilationJob(
+        &info, graph(), desc, &source_position_table_));
+    if (job->OptimizeGraph() != CompilationJob::SUCCEEDED ||
+        job->GenerateCode() != CompilationJob::SUCCEEDED)
+      return Handle<Code>::null();
+
+    Handle<Code> code = info.code();
+
+    // Length is always 2, since usually <wasm_obj, func_index> is stored in the
+    // deopt data. Here, we only store the function index.
+    DCHECK(code->deoptimization_data() == nullptr ||
+           code->deoptimization_data()->length() == 0);
+    Handle<FixedArray> deopt_data =
+        isolate()->factory()->NewFixedArray(2, TENURED);
+    deopt_data->set(1, Smi::FromInt(function_index_));
+    deopt_data->set_length(2);
+    code->set_deoptimization_data(*deopt_data);
+
 #ifdef ENABLE_DISASSEMBLER
-    if (!result.is_null() && FLAG_print_opt_code) {
+    if (FLAG_print_opt_code) {
       OFStream os(stdout);
-      result->Disassemble("wasm code", os);
+      code->Disassemble("wasm code", os);
     }
 #endif
 
-    return result;
+    return code;
   }
 
   uint32_t CompileAndAdd(uint16_t sig_index = 0) {
@@ -475,6 +526,16 @@
     if (function_) return function_;
     return &testing_module_->module->functions[function_index_];
   }
+
+  // Set the context, such that e.g. runtime functions can be called.
+  void SetModuleContext() {
+    if (!testing_module_->instance->context.is_null()) {
+      CHECK(testing_module_->instance->context.is_identical_to(
+          main_isolate()->native_context()));
+      return;
+    }
+    testing_module_->instance->context = main_isolate()->native_context();
+  }
 };
 
 // A helper class to build graphs from Wasm bytecode, generate machine
@@ -597,6 +658,15 @@
   }
 };
 
+// A macro to define tests that run in different engine configurations.
+// Currently only supports compiled tests, but a future
+// RunWasmInterpreted_##name version will allow each test to also run in the
+// interpreter.
+#define WASM_EXEC_TEST(name)                         \
+  void RunWasm_##name();                             \
+  TEST(RunWasmCompiled_##name) { RunWasm_##name(); } \
+  void RunWasm_##name()
+
 }  // namespace
 
 #endif