Bug 1561513 - Wasm: Restrict existing select instruction to numeric types. r=lth
authorRyan Hunt <rhunt@eqrion.net>
Wed, 25 Sep 2019 21:52:27 +0000
changeset 494984 16bba4255fff3cc6b10f43fb82d6d5e126509077
parent 494983 7a5339ab7cb77e57bea6f9c246a33ece4879df8d
child 494985 c1a81d62ead5ea21db50b90dd116b73abbed4e03
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: Restrict existing select instruction to numeric types. r=lth Issue: https://github.com/WebAssembly/reference-types/issues/42 The existing select instruction contains no typing information. As more complicated types are added, we will need to infer the result type as the least upper bound of the operands. This may be a complicated operation, so we will restrict the existing untyped instruction to operate only on the MVP value types, and add a new select instruction with type information. Differential Revision: https://phabricator.services.mozilla.com/D45863
js/src/wasm/WasmOpIter.h
--- a/js/src/wasm/WasmOpIter.h
+++ b/js/src/wasm/WasmOpIter.h
@@ -79,16 +79,29 @@ class StackType {
   }
 
   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::I32:
+      case Code::I64:
+      case Code::F32:
+      case Code::F64:
+        return true;
+      default:
+        return false;
+    }
+  }
+
   uint32_t refTypeIndex() const { return UnpackTypeCodeIndex(tc_); }
   bool isRef() const { return UnpackTypeCodeType(tc_) == TypeCode::Ref; }
 
   bool isReference() const { return IsReferenceType(tc_); }
 
   bool operator==(const StackType& that) const { return tc_ == that.tc_; }
   bool operator!=(const StackType& that) const { return tc_ != that.tc_; }
   bool operator==(Code that) const {
@@ -321,17 +334,16 @@ class MOZ_STACK_CLASS OpIter : private P
     valueStack_.infallibleAppend(tv);
   }
 
   void afterUnconditionalBranch() {
     valueStack_.shrinkTo(controlStack_.back().valueStackStart());
     controlStack_.back().setPolymorphicBase();
   }
 
-  inline bool Join(StackType one, StackType two, StackType* 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),
@@ -509,53 +521,16 @@ 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>::Join(StackType one, StackType two,
-                                 StackType* result) const {
-  if (MOZ_LIKELY(one == two)) {
-    *result = one;
-    return true;
-  }
-
-  if (one == StackType::TVar) {
-    *result = two;
-    return true;
-  }
-
-  if (two == StackType::TVar) {
-    *result = one;
-    return true;
-  }
-
-  if (one.isReference() && two.isReference()) {
-    if (env_.isRefSubtypeOf(NonTVarToValType(two), NonTVarToValType(one))) {
-      *result = one;
-      return true;
-    }
-
-    if (env_.isRefSubtypeOf(NonTVarToValType(one), NonTVarToValType(two))) {
-      *result = two;
-      return true;
-    }
-
-    // No subtyping relations between the two types.
-    *result = StackType::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;
@@ -1331,17 +1306,25 @@ inline bool OpIter<Policy>::readSelect(S
     return false;
   }
 
   StackType trueType;
   if (!popStackType(&trueType, trueValue)) {
     return false;
   }
 
-  if (!Join(falseType, trueType, type)) {
+  if (!falseType.isNumeric() || !trueType.isNumeric()) {
+    return fail("select operand types must be numeric");
+  }
+
+  if (falseType.code() == StackType::TVar) {
+    *type = trueType;
+  } else if (trueType.code() == StackType::TVar || falseType == trueType) {
+    *type = falseType;
+  } else {
     return fail("select operand types must match");
   }
 
   infalliblePush(*type);
   return true;
 }
 
 template <typename Policy>