Bug 1561513 - Wasm: Add bottom type and tweak validation algorithm. r=lth
authorRyan Hunt <rhunt@eqrion.net>
Wed, 25 Sep 2019 21:54:56 +0000
changeset 494985 c1a81d62ead5ea21db50b90dd116b73abbed4e03
parent 494984 16bba4255fff3cc6b10f43fb82d6d5e126509077
child 494986 7f894549b2877b0c44393a1957eafe092d92f727
push id114131
push userdluca@mozilla.com
push dateThu, 26 Sep 2019 09:47:34 +0000
treeherdermozilla-inbound@1dc1a755079a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslth
bugs1561513
milestone71.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1561513 - Wasm: Add bottom type and tweak validation algorithm. r=lth This commit renames TVar to represent the new Bottom type introduced in the reference types spec. Issue: https://github.com/WebAssembly/reference-types/issues/42 The only observable spec change so far is in validation of br_table which requires that the operand type is a subtype of all label types. With a bottom type, this may allow more code to validate than before. Differential Revision: https://phabricator.services.mozilla.com/D46641
js/src/jit-test/tests/wasm/regress/misc-control-flow.js
js/src/jit-test/tests/wasm/spec/unreached-invalid.wast.js
js/src/wasm/WasmBaselineCompile.cpp
js/src/wasm/WasmOpIter.h
testing/web-platform/mozilla/tests/wasm/js/unreached-invalid.wast.js
--- a/js/src/jit-test/tests/wasm/regress/misc-control-flow.js
+++ b/js/src/jit-test/tests/wasm/regress/misc-control-flow.js
@@ -197,27 +197,27 @@ wasmEvalText(`
 wasmFailValidateText(`
 (module
     (func (result i32)
       (loop
         (i32.const 0)
         (br_table 1 0 (i32.const 15))
       )
     )
-)`, /br_table targets must all have the same value type/);
+)`, /br_table operand must be subtype of all target types/);
 
 wasmFailValidateText(`
 (module
   (func (result i32)
     (loop i32
       (i32.const 0)
       (br_table 1 0 (i32.const 15))
     )
   )
-)`, /br_table targets must all have the same value type/);
+)`, /br_table operand must be subtype of all target types/);
 
 wasmValidateText(`
 (module
     (func
         (loop
           (i32.const 0)
           (br_table 1 0 (i32.const 15))
         )
--- a/js/src/jit-test/tests/wasm/spec/unreached-invalid.wast.js
+++ b/js/src/jit-test/tests/wasm/spec/unreached-invalid.wast.js
@@ -255,79 +255,76 @@ assert_invalid("\x00\x61\x73\x6d\x01\x00
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x94\x80\x80\x80\x00\x01\x8e\x80\x80\x80\x00\x00\x02\x40\x00\x43\x00\x00\x80\x3f\x0e\x00\x00\x0b\x0b");
 
 // unreached-invalid.wast:520
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x96\x80\x80\x80\x00\x01\x90\x80\x80\x80\x00\x00\x02\x7f\x00\x43\x00\x00\x00\x00\x41\x01\x0e\x00\x00\x0b\x0b");
 
 // unreached-invalid.wast:526
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x97\x80\x80\x80\x00\x01\x91\x80\x80\x80\x00\x00\x02\x40\x02\x7d\x00\x41\x01\x0e\x02\x00\x01\x00\x0b\x1a\x0b\x0b");
 
-// unreached-invalid.wast:538
-assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\xa1\x80\x80\x80\x00\x01\x9b\x80\x80\x80\x00\x00\x02\x7c\x02\x7d\x00\x41\x01\x0e\x02\x00\x01\x01\x0b\x1a\x44\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x1a\x0b");
-
-// unreached-invalid.wast:553
+// unreached-invalid.wast:539
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x00\x0b\x0b\x0b");
 
-// unreached-invalid.wast:559
+// unreached-invalid.wast:545
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8f\x80\x80\x80\x00\x01\x89\x80\x80\x80\x00\x00\x02\x40\x02\x40\x00\x0b\x0b\x0b");
 
-// unreached-invalid.wast:565
+// unreached-invalid.wast:551
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x02\x7e\x42\x00\x02\x40\x00\x0b\x0b\x0b");
 
-// unreached-invalid.wast:571
+// unreached-invalid.wast:557
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x42\x01\x00\x0b\x0b\x41\x09\x0b");
 
-// unreached-invalid.wast:578
+// unreached-invalid.wast:564
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x92\x80\x80\x80\x00\x01\x8c\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x0c\x01\x0b\x0b\x0b");
 
-// unreached-invalid.wast:584
+// unreached-invalid.wast:570
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x92\x80\x80\x80\x00\x01\x8c\x80\x80\x80\x00\x00\x02\x7f\x02\x40\x41\x00\x0c\x01\x0b\x0b\x0b");
 
-// unreached-invalid.wast:590
+// unreached-invalid.wast:576
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x94\x80\x80\x80\x00\x01\x8e\x80\x80\x80\x00\x00\x02\x7f\x42\x00\x02\x40\x41\x00\x0c\x01\x0b\x0b\x0b");
 
-// unreached-invalid.wast:597
+// unreached-invalid.wast:583
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x40\x02\x40\x41\x03\x02\x40\x0c\x02\x0b\x0b\x0b\x0b");
 
+// unreached-invalid.wast:589
+assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x7f\x02\x40\x02\x40\x41\x00\x0c\x02\x0b\x0b\x0b\x0b");
+
+// unreached-invalid.wast:595
+assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x97\x80\x80\x80\x00\x01\x91\x80\x80\x80\x00\x00\x02\x7f\x02\x7e\x42\x00\x02\x40\x41\x00\x0c\x02\x0b\x0b\x0b\x0b");
+
 // unreached-invalid.wast:603
-assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x7f\x02\x40\x02\x40\x41\x00\x0c\x02\x0b\x0b\x0b\x0b");
-
-// unreached-invalid.wast:609
-assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x97\x80\x80\x80\x00\x01\x91\x80\x80\x80\x00\x00\x02\x7f\x02\x7e\x42\x00\x02\x40\x41\x00\x0c\x02\x0b\x0b\x0b\x0b");
-
-// unreached-invalid.wast:617
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x96\x80\x80\x80\x00\x01\x90\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x42\x01\x0c\x01\x0b\x0b\x41\x09\x0b");
 
-// unreached-invalid.wast:624
+// unreached-invalid.wast:610
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x0f\x0b\x0b\x0b");
 
-// unreached-invalid.wast:630
+// unreached-invalid.wast:616
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x02\x40\x02\x40\x41\x00\x0f\x0b\x0b\x0b");
 
+// unreached-invalid.wast:622
+assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x93\x80\x80\x80\x00\x01\x8d\x80\x80\x80\x00\x00\x02\x7e\x42\x00\x02\x40\x41\x00\x0f\x0b\x0b\x0b");
+
+// unreached-invalid.wast:628
+assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x97\x80\x80\x80\x00\x01\x91\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x42\x01\x41\x00\x0f\x0b\x0b\x41\x09\x0b");
+
 // unreached-invalid.wast:636
-assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x93\x80\x80\x80\x00\x01\x8d\x80\x80\x80\x00\x00\x02\x7e\x42\x00\x02\x40\x41\x00\x0f\x0b\x0b\x0b");
+assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x03\x40\x41\x03\x02\x40\x00\x0b\x0b\x0b");
 
 // unreached-invalid.wast:642
-assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x97\x80\x80\x80\x00\x01\x91\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x42\x01\x41\x00\x0f\x0b\x0b\x41\x09\x0b");
-
-// unreached-invalid.wast:650
-assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x03\x40\x41\x03\x02\x40\x00\x0b\x0b\x0b");
-
-// unreached-invalid.wast:656
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8f\x80\x80\x80\x00\x01\x89\x80\x80\x80\x00\x00\x03\x40\x02\x40\x00\x0b\x0b\x0b");
 
-// unreached-invalid.wast:662
+// unreached-invalid.wast:648
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x03\x7e\x42\x00\x02\x40\x00\x0b\x0b\x0b");
 
-// unreached-invalid.wast:669
+// unreached-invalid.wast:655
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8e\x80\x80\x80\x00\x01\x88\x80\x80\x80\x00\x00\x03\x40\x01\x0c\x00\x0b\x0b");
 
-// unreached-invalid.wast:675
+// unreached-invalid.wast:661
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8f\x80\x80\x80\x00\x01\x89\x80\x80\x80\x00\x00\x03\x40\x41\x00\x0c\x00\x0b\x0b");
 
-// unreached-invalid.wast:682
+// unreached-invalid.wast:668
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8d\x80\x80\x80\x00\x01\x87\x80\x80\x80\x00\x01\x01\x7f\x00\x22\x00\x0b");
 
-// unreached-invalid.wast:689
+// unreached-invalid.wast:675
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x7f\x02\x40\x00\x41\x00\x0d\x01\x0b\x41\x00\x0b\x0b");
 
-// unreached-invalid.wast:700
+// unreached-invalid.wast:686
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7e\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8c\x80\x80\x80\x00\x01\x86\x80\x80\x80\x00\x00\x00\x0d\x00\xad\x0b");
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -9551,17 +9551,17 @@ bool BaseCompiler::emitSelect() {
   }
 
   // I32 condition on top, then false, then true.
 
   Label done;
   BranchState b(&done);
   emitBranchSetup(&b);
 
-  switch (NonTVarToValType(type).code()) {
+  switch (NonBottomToValType(type).code()) {
     case ValType::I32: {
       RegI32 r, rs;
       pop2xI32(&r, &rs);
       emitBranchPerform(&b);
       moveI32(rs, r);
       masm.bind(&done);
       freeI32(rs);
       pushI32(r);
--- a/js/src/wasm/WasmOpIter.h
+++ b/js/src/wasm/WasmOpIter.h
@@ -64,34 +64,34 @@ class StackType {
     F32 = uint8_t(ValType::F32),
     F64 = uint8_t(ValType::F64),
 
     AnyRef = uint8_t(ValType::AnyRef),
     FuncRef = uint8_t(ValType::FuncRef),
     Ref = uint8_t(ValType::Ref),
     NullRef = uint8_t(ValType::NullRef),
 
-    TVar = uint8_t(TypeCode::Limit),
+    Bottom = uint8_t(TypeCode::Limit),
   };
 
   StackType() : tc_(InvalidPackedTypeCode()) {}
 
   MOZ_IMPLICIT StackType(Code c) : tc_(PackTypeCode(TypeCode(c))) {
     MOZ_ASSERT(isValidCode());
   }
 
   explicit StackType(const ValType& t) : tc_(t.packed()) {}
 
   PackedTypeCode packed() const { return tc_; }
 
   Code code() const { return Code(UnpackTypeCodeType(tc_)); }
 
   bool isNumeric() const {
     switch (code()) {
-      case Code::TVar:
+      case Code::Bottom:
       case Code::I32:
       case Code::I64:
       case Code::F32:
       case Code::F64:
         return true;
       default:
         return false;
     }
@@ -106,18 +106,18 @@ class StackType {
   bool operator!=(const StackType& that) const { return tc_ != that.tc_; }
   bool operator==(Code that) const {
     MOZ_ASSERT(that != Code::Ref);
     return code() == that;
   }
   bool operator!=(Code that) const { return !(*this == that); }
 };
 
-static inline ValType NonTVarToValType(StackType type) {
-  MOZ_ASSERT(type != StackType::TVar);
+static inline ValType NonBottomToValType(StackType type) {
+  MOZ_ASSERT(type != StackType::Bottom);
   return ValType(type.packed());
 }
 
 #ifdef DEBUG
 // Families of opcodes that share a signature and validation logic.
 enum class OpKind {
   Block,
   Loop,
@@ -241,17 +241,17 @@ class ControlStackEntry {
 };
 
 template <typename Value>
 class TypeAndValue {
   // Use a Pair to optimize away empty Value.
   mozilla::Pair<StackType, Value> tv_;
 
  public:
-  TypeAndValue() : tv_(StackType::TVar, Value()) {}
+  TypeAndValue() : tv_(StackType::Bottom, Value()) {}
   explicit TypeAndValue(StackType type) : tv_(type, Value()) {}
   explicit TypeAndValue(ValType type) : tv_(StackType(type), Value()) {}
   TypeAndValue(StackType type, Value value) : tv_(type, value) {}
   TypeAndValue(ValType type, Value value) : tv_(StackType(type), value) {}
   StackType type() const { return tv_.first(); }
   StackType& typeRef() { return tv_.first(); }
   Value value() const { return tv_.second(); }
   void setValue(Value value) { tv_.second() = value; }
@@ -302,24 +302,27 @@ class MOZ_STACK_CLASS OpIter : private P
                                 Vector<Value, 8, SystemAllocPolicy>* values);
 
   MOZ_MUST_USE bool failEmptyStack();
   MOZ_MUST_USE bool popStackType(StackType* type, Value* value);
   MOZ_MUST_USE bool popWithType(ValType valType, Value* value);
   MOZ_MUST_USE bool popWithType(ExprType expectedType, Value* value);
   MOZ_MUST_USE bool topWithType(ExprType expectedType, Value* value);
   MOZ_MUST_USE bool topWithType(ValType valType, Value* value);
+  MOZ_MUST_USE bool topIsType(ValType expectedType, StackType* actualType,
+                              Value* value);
 
   MOZ_MUST_USE bool pushControl(LabelKind kind, ExprType type);
   MOZ_MUST_USE bool checkStackAtEndOfBlock(ExprType* type, Value* value);
   MOZ_MUST_USE bool getControl(uint32_t relativeDepth,
                                ControlStackEntry<ControlItem>** controlEntry);
   MOZ_MUST_USE bool checkBranchValue(uint32_t relativeDepth, ExprType* type,
                                      Value* value);
   MOZ_MUST_USE bool checkBrTableEntry(uint32_t* relativeDepth,
+                                      uint32_t* branchValueArity,
                                       ExprType* branchValueType,
                                       Value* branchValue);
 
   MOZ_MUST_USE bool push(StackType t) { return valueStack_.emplaceBack(t); }
   MOZ_MUST_USE bool push(ValType t) { return valueStack_.emplaceBack(t); }
   MOZ_MUST_USE bool push(ExprType t) {
     return IsVoid(t) || push(NonVoidToValType(t));
   }
@@ -334,16 +337,21 @@ class MOZ_STACK_CLASS OpIter : private P
     valueStack_.infallibleAppend(tv);
   }
 
   void afterUnconditionalBranch() {
     valueStack_.shrinkTo(controlStack_.back().valueStackStart());
     controlStack_.back().setPolymorphicBase();
   }
 
+  // Compute a type that is a supertype of one and two. This type is not
+  // guaranteed to be minimal; there may be a more specific supertype of one
+  // and two that this type is a supertype of.
+  inline bool weakMeet(ExprType one, ExprType two, ExprType* result) const;
+
   inline bool checkIsSubtypeOf(ValType lhs, ValType rhs);
 
  public:
   typedef Vector<Value, 8, SystemAllocPolicy> ValueVector;
 
 #ifdef DEBUG
   explicit OpIter(const ModuleEnvironment& env, Decoder& decoder)
       : d_(decoder),
@@ -521,16 +529,32 @@ class MOZ_STACK_CLASS OpIter : private P
   ControlItem& controlOutermost() { return controlStack_[0].controlItem(); }
 
   // Test whether the control-stack is empty, meaning we've consumed the final
   // end of the function body.
   bool controlStackEmpty() const { return controlStack_.empty(); }
 };
 
 template <typename Policy>
+inline bool OpIter<Policy>::weakMeet(ExprType one, ExprType two,
+                                     ExprType* result) const {
+  if (MOZ_LIKELY(one == two)) {
+    *result = one;
+    return true;
+  }
+
+  if (one.isReference() && two.isReference()) {
+    *result = ExprType::AnyRef;
+    return true;
+  }
+
+  return false;
+}
+
+template <typename Policy>
 inline bool OpIter<Policy>::checkIsSubtypeOf(ValType actual, ValType expected) {
   if (actual == expected) {
     return true;
   }
 
   if (actual.isReference() && expected.isReference() &&
       env_.isRefSubtypeOf(actual, expected)) {
     return true;
@@ -572,30 +596,30 @@ inline bool OpIter<Policy>::fail_ctx(con
 }
 
 template <typename Policy>
 inline bool OpIter<Policy>::failEmptyStack() {
   return valueStack_.empty() ? fail("popping value from empty stack")
                              : fail("popping value from outside block");
 }
 
-// This function pops exactly one value from the stack, yielding TVar types in
+// This function pops exactly one value from the stack, yielding Bottom types in
 // various cases and therefore making it the caller's responsibility to do the
-// right thing for StackType::TVar. Prefer (pop|top)WithType.
+// right thing for StackType::Bottom. Prefer (pop|top)WithType.
 template <typename Policy>
 inline bool OpIter<Policy>::popStackType(StackType* type, Value* value) {
   ControlStackEntry<ControlItem>& block = controlStack_.back();
 
   MOZ_ASSERT(valueStack_.length() >= block.valueStackStart());
   if (MOZ_UNLIKELY(valueStack_.length() == block.valueStackStart())) {
     // If the base of this block's stack is polymorphic, then we can pop a
     // dummy value of any type; it won't be used since we're in unreachable
     // code.
     if (block.polymorphicBase()) {
-      *type = StackType::TVar;
+      *type = StackType::Bottom;
       *value = Value();
 
       // Maintain the invariant that, after a pop, there is always memory
       // reserved to push a value infallibly.
       return valueStack_.reserve(valueStack_.length() + 1);
     }
 
     return failEmptyStack();
@@ -612,35 +636,36 @@ inline bool OpIter<Policy>::popStackType
 // expected type which can either be a specific value type or a type variable.
 template <typename Policy>
 inline bool OpIter<Policy>::popWithType(ValType expectedType, Value* value) {
   StackType stackType(expectedType);
   if (!popStackType(&stackType, value)) {
     return false;
   }
 
-  return stackType == StackType::TVar ||
-         checkIsSubtypeOf(NonTVarToValType(stackType), expectedType);
+  return stackType == StackType::Bottom ||
+         checkIsSubtypeOf(NonBottomToValType(stackType), expectedType);
 }
 
 // This function pops as many types from the stack as determined by the given
 // signature. Currently, all signatures are limited to 0 or 1 types, with
 // ExprType::Void meaning 0 and all other ValTypes meaning 1, but this will be
 // generalized in the future.
 template <typename Policy>
 inline bool OpIter<Policy>::popWithType(ExprType expectedType, Value* value) {
   if (IsVoid(expectedType)) {
     *value = Value();
     return true;
   }
 
   return popWithType(NonVoidToValType(expectedType), value);
 }
 
-// This function is just an optimization of popWithType + push.
+// This function is equivalent to: popWithType(expectedType);
+// push(expectedType);
 template <typename Policy>
 inline bool OpIter<Policy>::topWithType(ValType expectedType, Value* value) {
   ControlStackEntry<ControlItem>& block = controlStack_.back();
 
   MOZ_ASSERT(valueStack_.length() >= block.valueStackStart());
   if (valueStack_.length() == block.valueStackStart()) {
     // If the base of this block's stack is polymorphic, then we can just
     // pull out a dummy value of the expected type; it won't be used since
@@ -656,23 +681,23 @@ inline bool OpIter<Policy>::topWithType(
       return true;
     }
 
     return failEmptyStack();
   }
 
   TypeAndValue<Value>& observed = valueStack_.back();
 
-  if (observed.type() == StackType::TVar) {
+  if (observed.type() == StackType::Bottom) {
     observed.typeRef() = StackType(expectedType);
     *value = Value();
     return true;
   }
 
-  if (!checkIsSubtypeOf(NonTVarToValType(observed.type()), expectedType)) {
+  if (!checkIsSubtypeOf(NonBottomToValType(observed.type()), expectedType)) {
     return false;
   }
 
   *value = observed.value();
   return true;
 }
 
 template <typename Policy>
@@ -680,16 +705,54 @@ inline bool OpIter<Policy>::topWithType(
   if (IsVoid(expectedType)) {
     *value = Value();
     return true;
   }
 
   return topWithType(NonVoidToValType(expectedType), value);
 }
 
+// This function checks that the top of the stack is a subtype of expectedType
+// and returns the value if so.
+template <typename Policy>
+inline bool OpIter<Policy>::topIsType(ValType expectedType,
+                                      StackType* actualType, Value* value) {
+  ControlStackEntry<ControlItem>& block = controlStack_.back();
+
+  MOZ_ASSERT(valueStack_.length() >= block.valueStackStart());
+  if (valueStack_.length() == block.valueStackStart()) {
+    // If the base of this block's stack is polymorphic, then we can just
+    // pull out a dummy value of the expected type; it won't be used since
+    // we're in unreachable code.
+    if (block.polymorphicBase()) {
+      *actualType = StackType::Bottom;
+      *value = Value();
+      return true;
+    }
+
+    return failEmptyStack();
+  }
+
+  TypeAndValue<Value>& observed = valueStack_.back();
+
+  if (observed.type() == StackType::Bottom) {
+    *actualType = StackType::Bottom;
+    *value = Value();
+    return true;
+  }
+
+  if (!checkIsSubtypeOf(NonBottomToValType(observed.type()), expectedType)) {
+    return false;
+  }
+
+  *actualType = observed.type();
+  *value = observed.value();
+  return true;
+}
+
 template <typename Policy>
 inline bool OpIter<Policy>::pushControl(LabelKind kind, ExprType type) {
   return controlStack_.emplaceBack(kind, type, valueStack_.length());
 }
 
 template <typename Policy>
 inline bool OpIter<Policy>::checkStackAtEndOfBlock(ExprType* type,
                                                    Value* value) {
@@ -964,42 +1027,76 @@ inline bool OpIter<Policy>::readBrIf(uin
 
   if (!popWithType(ValType::I32, condition)) {
     return false;
   }
 
   return checkBranchValue(*relativeDepth, type, value);
 }
 
+#define UNKNOWN_ARITY UINT32_MAX
+
 template <typename Policy>
 inline bool OpIter<Policy>::checkBrTableEntry(uint32_t* relativeDepth,
+                                              uint32_t* branchValueArity,
                                               ExprType* branchValueType,
                                               Value* branchValue) {
   if (!readVarU32(relativeDepth)) {
     return false;
   }
 
+  ControlStackEntry<ControlItem>* block = nullptr;
+  if (!getControl(*relativeDepth, &block)) {
+    return false;
+  }
+
   // For the first encountered branch target, do a normal branch value type
-  // check which will change *branchValueType to a non-sentinel value. For all
-  // subsequent branch targets, check that the branch target matches the
-  // now-known branch value type.
+  // check which will change *branchValueArity and *branchValueType to a
+  // non-sentinel value. For all subsequent branch targets, check that the
+  // branch target arity and type matches the now-known branch value arity
+  // and type. This will need to change with multi-value.
+  uint32_t labelTypeArity = IsVoid(block->branchTargetType()) ? 0 : 1;
+
+  if (*branchValueArity == UNKNOWN_ARITY) {
+    *branchValueArity = labelTypeArity;
+  } else if (*branchValueArity != labelTypeArity) {
+    return fail("br_table operand must be subtype of all target types");
+  }
+
+  // If the label types are void, no need to check type on the stack
+  if (labelTypeArity == 0) {
+    *branchValueType = ExprType::Void;
+    *branchValue = Value();
+    return true;
+  }
+
+  // Check that the value on the stack is a subtype of the label
+  StackType actualBranchValueType;
+  if (!topIsType(NonVoidToValType(block->branchTargetType()),
+                 &actualBranchValueType, branchValue)) {
+    return false;
+  }
+
+  // If the value on the stack is the bottom type, it will by definition be a
+  // subtype of every possible label type. This also implies that the label
+  // types may not have a subtype relation, and so we cannot report a branch
+  // value type. Fortunately this only happens in unreachable code, where we
+  // don't use the branch value type.
+  if (actualBranchValueType == StackType::Bottom) {
+    *branchValueType = ExprType::Limit;
+    return true;
+  }
+
+  // Compute the branch value type in all other cases
 
   if (*branchValueType == ExprType::Limit) {
-    if (!checkBranchValue(*relativeDepth, branchValueType, branchValue)) {
-      return false;
-    }
-  } else {
-    ControlStackEntry<ControlItem>* block = nullptr;
-    if (!getControl(*relativeDepth, &block)) {
-      return false;
-    }
-
-    if (*branchValueType != block->branchTargetType()) {
-      return fail("br_table targets must all have the same value type");
-    }
+    *branchValueType = block->branchTargetType();
+  } else if (!weakMeet(*branchValueType, block->branchTargetType(),
+                       branchValueType)) {
+    return fail("br_table operand must be subtype of all target types");
   }
 
   return true;
 }
 
 template <typename Policy>
 inline bool OpIter<Policy>::readBrTable(Uint32Vector* depths,
                                         uint32_t* defaultDepth,
@@ -1019,34 +1116,39 @@ inline bool OpIter<Policy>::readBrTable(
   if (!popWithType(ValType::I32, index)) {
     return false;
   }
 
   if (!depths->resize(tableLength)) {
     return false;
   }
 
+  uint32_t branchValueArity = UNKNOWN_ARITY;
   *branchValueType = ExprType::Limit;
 
   for (uint32_t i = 0; i < tableLength; i++) {
-    if (!checkBrTableEntry(&(*depths)[i], branchValueType, branchValue)) {
+    if (!checkBrTableEntry(&(*depths)[i], &branchValueArity, branchValueType,
+                           branchValue)) {
       return false;
     }
   }
 
-  if (!checkBrTableEntry(defaultDepth, branchValueType, branchValue)) {
+  if (!checkBrTableEntry(defaultDepth, &branchValueArity, branchValueType,
+                         branchValue)) {
     return false;
   }
 
-  MOZ_ASSERT(*branchValueType != ExprType::Limit);
+  MOZ_ASSERT(branchValueArity != UNKNOWN_ARITY);
 
   afterUnconditionalBranch();
   return true;
 }
 
+#undef UNKNOWN_ARITY
+
 template <typename Policy>
 inline bool OpIter<Policy>::readUnreachable() {
   MOZ_ASSERT(Classify(op_) == OpKind::Unreachable);
 
   afterUnconditionalBranch();
   return true;
 }
 
@@ -1310,19 +1412,19 @@ inline bool OpIter<Policy>::readSelect(S
   if (!popStackType(&trueType, trueValue)) {
     return false;
   }
 
   if (!falseType.isNumeric() || !trueType.isNumeric()) {
     return fail("select operand types must be numeric");
   }
 
-  if (falseType.code() == StackType::TVar) {
+  if (falseType.code() == StackType::Bottom) {
     *type = trueType;
-  } else if (trueType.code() == StackType::TVar || falseType == trueType) {
+  } else if (trueType.code() == StackType::Bottom || falseType == trueType) {
     *type = falseType;
   } else {
     return fail("select operand types must match");
   }
 
   infalliblePush(*type);
   return true;
 }
--- a/testing/web-platform/mozilla/tests/wasm/js/unreached-invalid.wast.js
+++ b/testing/web-platform/mozilla/tests/wasm/js/unreached-invalid.wast.js
@@ -256,81 +256,78 @@ assert_invalid("\x00\x61\x73\x6d\x01\x00
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x94\x80\x80\x80\x00\x01\x8e\x80\x80\x80\x00\x00\x02\x40\x00\x43\x00\x00\x80\x3f\x0e\x00\x00\x0b\x0b");
 
 // unreached-invalid.wast:520
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x96\x80\x80\x80\x00\x01\x90\x80\x80\x80\x00\x00\x02\x7f\x00\x43\x00\x00\x00\x00\x41\x01\x0e\x00\x00\x0b\x0b");
 
 // unreached-invalid.wast:526
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x97\x80\x80\x80\x00\x01\x91\x80\x80\x80\x00\x00\x02\x40\x02\x7d\x00\x41\x01\x0e\x02\x00\x01\x00\x0b\x1a\x0b\x0b");
 
-// unreached-invalid.wast:538
-assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\xa1\x80\x80\x80\x00\x01\x9b\x80\x80\x80\x00\x00\x02\x7c\x02\x7d\x00\x41\x01\x0e\x02\x00\x01\x01\x0b\x1a\x44\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x1a\x0b");
-
-// unreached-invalid.wast:553
+// unreached-invalid.wast:539
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x00\x0b\x0b\x0b");
 
-// unreached-invalid.wast:559
+// unreached-invalid.wast:545
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8f\x80\x80\x80\x00\x01\x89\x80\x80\x80\x00\x00\x02\x40\x02\x40\x00\x0b\x0b\x0b");
 
-// unreached-invalid.wast:565
+// unreached-invalid.wast:551
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x02\x7e\x42\x00\x02\x40\x00\x0b\x0b\x0b");
 
-// unreached-invalid.wast:571
+// unreached-invalid.wast:557
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x42\x01\x00\x0b\x0b\x41\x09\x0b");
 
-// unreached-invalid.wast:578
+// unreached-invalid.wast:564
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x92\x80\x80\x80\x00\x01\x8c\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x0c\x01\x0b\x0b\x0b");
 
-// unreached-invalid.wast:584
+// unreached-invalid.wast:570
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x92\x80\x80\x80\x00\x01\x8c\x80\x80\x80\x00\x00\x02\x7f\x02\x40\x41\x00\x0c\x01\x0b\x0b\x0b");
 
-// unreached-invalid.wast:590
+// unreached-invalid.wast:576
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x94\x80\x80\x80\x00\x01\x8e\x80\x80\x80\x00\x00\x02\x7f\x42\x00\x02\x40\x41\x00\x0c\x01\x0b\x0b\x0b");
 
-// unreached-invalid.wast:597
+// unreached-invalid.wast:583
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x40\x02\x40\x41\x03\x02\x40\x0c\x02\x0b\x0b\x0b\x0b");
 
-// unreached-invalid.wast:603
+// unreached-invalid.wast:589
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x7f\x02\x40\x02\x40\x41\x00\x0c\x02\x0b\x0b\x0b\x0b");
 
-// unreached-invalid.wast:609
+// unreached-invalid.wast:595
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x97\x80\x80\x80\x00\x01\x91\x80\x80\x80\x00\x00\x02\x7f\x02\x7e\x42\x00\x02\x40\x41\x00\x0c\x02\x0b\x0b\x0b\x0b");
 
-// unreached-invalid.wast:617
+// unreached-invalid.wast:603
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x96\x80\x80\x80\x00\x01\x90\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x42\x01\x0c\x01\x0b\x0b\x41\x09\x0b");
 
-// unreached-invalid.wast:624
+// unreached-invalid.wast:610
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x0f\x0b\x0b\x0b");
 
-// unreached-invalid.wast:630
+// unreached-invalid.wast:616
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x02\x40\x02\x40\x41\x00\x0f\x0b\x0b\x0b");
 
+// unreached-invalid.wast:622
+assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x93\x80\x80\x80\x00\x01\x8d\x80\x80\x80\x00\x00\x02\x7e\x42\x00\x02\x40\x41\x00\x0f\x0b\x0b\x0b");
+
+// unreached-invalid.wast:628
+assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x97\x80\x80\x80\x00\x01\x91\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x42\x01\x41\x00\x0f\x0b\x0b\x41\x09\x0b");
+
 // unreached-invalid.wast:636
-assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x93\x80\x80\x80\x00\x01\x8d\x80\x80\x80\x00\x00\x02\x7e\x42\x00\x02\x40\x41\x00\x0f\x0b\x0b\x0b");
-
-// unreached-invalid.wast:642
-assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x97\x80\x80\x80\x00\x01\x91\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x42\x01\x41\x00\x0f\x0b\x0b\x41\x09\x0b");
-
-// unreached-invalid.wast:650
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x03\x40\x41\x03\x02\x40\x00\x0b\x0b\x0b");
 
-// unreached-invalid.wast:656
+// unreached-invalid.wast:642
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8f\x80\x80\x80\x00\x01\x89\x80\x80\x80\x00\x00\x03\x40\x02\x40\x00\x0b\x0b\x0b");
 
-// unreached-invalid.wast:662
+// unreached-invalid.wast:648
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x03\x7e\x42\x00\x02\x40\x00\x0b\x0b\x0b");
 
-// unreached-invalid.wast:669
+// unreached-invalid.wast:655
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8e\x80\x80\x80\x00\x01\x88\x80\x80\x80\x00\x00\x03\x40\x01\x0c\x00\x0b\x0b");
 
+// unreached-invalid.wast:661
+assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8f\x80\x80\x80\x00\x01\x89\x80\x80\x80\x00\x00\x03\x40\x41\x00\x0c\x00\x0b\x0b");
+
+// unreached-invalid.wast:668
+assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8d\x80\x80\x80\x00\x01\x87\x80\x80\x80\x00\x01\x01\x7f\x00\x22\x00\x0b");
+
 // unreached-invalid.wast:675
-assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8f\x80\x80\x80\x00\x01\x89\x80\x80\x80\x00\x00\x03\x40\x41\x00\x0c\x00\x0b\x0b");
-
-// unreached-invalid.wast:682
-assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8d\x80\x80\x80\x00\x01\x87\x80\x80\x80\x00\x01\x01\x7f\x00\x22\x00\x0b");
-
-// unreached-invalid.wast:689
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x7f\x02\x40\x00\x41\x00\x0d\x01\x0b\x41\x00\x0b\x0b");
 
-// unreached-invalid.wast:700
+// unreached-invalid.wast:686
 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7e\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8c\x80\x80\x80\x00\x01\x86\x80\x80\x80\x00\x00\x00\x0d\x00\xad\x0b");
 reinitializeRegistry();
 })();