Bug 1416766: Int64 wasm globals should cause a link failure at instanciation time, not compile time; r=luke
authorBenjamin Bouvier <benj@benj.me>
Thu, 09 Nov 2017 16:30:42 +0100
changeset 392009 91858a00db9181ba4cc13fd44315cb9bed73a01c
parent 392008 6053c68a9bc63a2fcc6c1449e15cc0e85fa23279
child 392010 75c9879941ee6187423df2158739d20e37e40a05
push id32909
push usercbrindusan@mozilla.com
push dateWed, 15 Nov 2017 22:25:14 +0000
treeherdermozilla-central@f41930a869a8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1416766
milestone59.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 1416766: Int64 wasm globals should cause a link failure at instanciation time, not compile time; r=luke MozReview-Commit-ID: 5Ryl47naf9R
js/src/jit-test/tests/wasm/globals.js
js/src/js.msg
js/src/wasm/WasmInstance.cpp
js/src/wasm/WasmJS.cpp
js/src/wasm/WasmModule.cpp
js/src/wasm/WasmValidate.cpp
--- a/js/src/jit-test/tests/wasm/globals.js
+++ b/js/src/jit-test/tests/wasm/globals.js
@@ -223,18 +223,23 @@ function testInitExpr(type, initialValue
 }
 
 testInitExpr('i32', 13, 37, x => x|0);
 testInitExpr('f32', 13.37, 0.1989, Math.fround);
 testInitExpr('f64', 13.37, 0.1989, x => +x);
 
 // Int64.
 {
-    wasmFailValidateText(`(module (import "globals" "x" (global i64)))`, /can't import.* an Int64 global/);
-    wasmFailValidateText(`(module (global i64 (i64.const 42)) (export "" global 0))`, /can't .*export an Int64 global/);
+    let module = new WebAssembly.Module(wasmTextToBinary(`(module (import "globals" "x" (global i64)))`));
+    assertErrorMessage(() => new WebAssembly.Instance(module, {globals: {x:42}}),
+                       WebAssembly.LinkError,
+                       /cannot pass i64 to or from JS/);
+
+    module = new WebAssembly.Module(wasmTextToBinary(`(module (global i64 (i64.const 42)) (export "" global 0))`));
+    assertErrorMessage(() => new WebAssembly.Instance(module), WebAssembly.LinkError, /cannot pass i64 to or from JS/);
 
     setJitCompilerOption('wasm.test-mode', 1);
     testInner('i64', '0x531642753864975F', '0x123456789abcdef0', createI64, assertEqI64);
     testInitExpr('i64', '0x531642753864975F', '0x123456789abcdef0', createI64, assertEqI64);
 
     module = wasmEvalText(`(module
      (import "globals" "x" (global i64))
      (global i64 (i64.const 0xFAFADADABABA))
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -361,16 +361,17 @@ MSG_DEF(JSMSG_USE_ASM_TYPE_OK,         1
 
 // wasm
 MSG_DEF(JSMSG_WASM_COMPILE_ERROR,      1, JSEXN_WASMCOMPILEERROR, "{0}")
 MSG_DEF(JSMSG_WASM_BAD_IMPORT_TYPE,    2, JSEXN_WASMLINKERROR, "import object field '{0}' is not a {1}")
 MSG_DEF(JSMSG_WASM_BAD_IMPORT_SIG,     2, JSEXN_WASMLINKERROR, "imported function '{0}.{1}' signature mismatch")
 MSG_DEF(JSMSG_WASM_BAD_IMP_SIZE,       1, JSEXN_WASMLINKERROR, "imported {0} with incompatible size")
 MSG_DEF(JSMSG_WASM_BAD_IMP_MAX,        1, JSEXN_WASMLINKERROR, "imported {0} with incompatible maximum size")
 MSG_DEF(JSMSG_WASM_BAD_FIT,            2, JSEXN_WASMLINKERROR, "{0} segment does not fit in {1}")
+MSG_DEF(JSMSG_WASM_BAD_I64_LINK,       0, JSEXN_WASMLINKERROR, "cannot pass i64 to or from JS")
 MSG_DEF(JSMSG_WASM_IND_CALL_TO_NULL,   0, JSEXN_WASMRUNTIMEERROR, "indirect call to null")
 MSG_DEF(JSMSG_WASM_IND_CALL_BAD_SIG,   0, JSEXN_WASMRUNTIMEERROR, "indirect call signature mismatch")
 MSG_DEF(JSMSG_WASM_UNREACHABLE,        0, JSEXN_WASMRUNTIMEERROR, "unreachable executed")
 MSG_DEF(JSMSG_WASM_INTEGER_OVERFLOW,   0, JSEXN_WASMRUNTIMEERROR, "integer overflow")
 MSG_DEF(JSMSG_WASM_INVALID_CONVERSION, 0, JSEXN_WASMRUNTIMEERROR, "invalid conversion to integer")
 MSG_DEF(JSMSG_WASM_INT_DIVIDE_BY_ZERO, 0, JSEXN_WASMRUNTIMEERROR, "integer divide by zero")
 MSG_DEF(JSMSG_WASM_OUT_OF_BOUNDS,      0, JSEXN_WASMRUNTIMEERROR, "index out of bounds")
 MSG_DEF(JSMSG_WASM_UNALIGNED_ACCESS,   0, JSEXN_WASMRUNTIMEERROR, "unaligned memory access")
@@ -379,17 +380,17 @@ MSG_DEF(JSMSG_WASM_BAD_GROW,           1
 MSG_DEF(JSMSG_WASM_BAD_BUF_ARG,        0, JSEXN_TYPEERR,     "first argument must be an ArrayBuffer or typed array object")
 MSG_DEF(JSMSG_WASM_BAD_MOD_ARG,        0, JSEXN_TYPEERR,     "first argument must be a WebAssembly.Module")
 MSG_DEF(JSMSG_WASM_BAD_BUF_MOD_ARG,    0, JSEXN_TYPEERR,     "first argument must be a WebAssembly.Module, ArrayBuffer or typed array object")
 MSG_DEF(JSMSG_WASM_BAD_DESC_ARG,       1, JSEXN_TYPEERR,     "first argument must be a {0} descriptor")
 MSG_DEF(JSMSG_WASM_BAD_ELEMENT,        0, JSEXN_TYPEERR,     "\"element\" property of table descriptor must be \"anyfunc\"")
 MSG_DEF(JSMSG_WASM_BAD_IMPORT_ARG,     0, JSEXN_TYPEERR,     "second argument must be an object")
 MSG_DEF(JSMSG_WASM_BAD_IMPORT_FIELD,   1, JSEXN_TYPEERR,     "import object field '{0}' is not an Object")
 MSG_DEF(JSMSG_WASM_BAD_TABLE_VALUE,    0, JSEXN_TYPEERR,     "can only assign WebAssembly exported functions to Table")
-MSG_DEF(JSMSG_WASM_BAD_I64,            0, JSEXN_TYPEERR,     "cannot pass i64 to or from JS")
+MSG_DEF(JSMSG_WASM_BAD_I64_TYPE,       0, JSEXN_TYPEERR,     "cannot pass i64 to or from JS")
 MSG_DEF(JSMSG_WASM_NO_TRANSFER,        0, JSEXN_TYPEERR,     "cannot transfer WebAssembly/asm.js ArrayBuffer")
 MSG_DEF(JSMSG_WASM_STREAM_ERROR,       0, JSEXN_TYPEERR,     "stream error during WebAssembly compilation")
 MSG_DEF(JSMSG_WASM_TEXT_FAIL,          1, JSEXN_SYNTAXERR,   "wasm text error: {0}")
 
 // Proxy
 MSG_DEF(JSMSG_BAD_TRAP_RETURN_VALUE,   2, JSEXN_TYPEERR,"trap {1} for {0} returned a primitive value")
 MSG_DEF(JSMSG_BAD_GETPROTOTYPEOF_TRAP_RETURN,0,JSEXN_TYPEERR,"proxy getPrototypeOf handler returned a non-object, non-null value")
 MSG_DEF(JSMSG_INCONSISTENT_GETPROTOTYPEOF_TRAP,0,JSEXN_TYPEERR,"proxy getPrototypeOf handler didn't return the target object's prototype")
--- a/js/src/wasm/WasmInstance.cpp
+++ b/js/src/wasm/WasmInstance.cpp
@@ -145,17 +145,17 @@ Instance::callImport(JSContext* cx, uint
           case ValType::F32:
             args[i].set(JS::CanonicalizedDoubleValue(*(float*)&argv[i]));
             break;
           case ValType::F64:
             args[i].set(JS::CanonicalizedDoubleValue(*(double*)&argv[i]));
             break;
           case ValType::I64: {
             if (!JitOptions.wasmTestMode) {
-                JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64);
+                JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64_TYPE);
                 return false;
             }
             RootedObject obj(cx, CreateI64Object(cx, *(int64_t*)&argv[i]));
             if (!obj)
                 return false;
             args[i].set(ObjectValue(*obj));
             hasI64Arg = true;
             break;
@@ -175,17 +175,17 @@ Instance::callImport(JSContext* cx, uint
     RootedFunction importFun(cx, &import.obj->as<JSFunction>());
     RootedValue fval(cx, ObjectValue(*import.obj));
     RootedValue thisv(cx, UndefinedValue());
     if (!Call(cx, fval, thisv, args, rval))
         return false;
 
     // Throw an error if returning i64 and not in test mode.
     if (!JitOptions.wasmTestMode && fi.sig().ret() == ExprType::I64) {
-        JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64);
+        JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64_TYPE);
         return false;
     }
 
     // Don't try to optimize if the function has at least one i64 arg or if
     // it returns an int64. GenerateJitExit relies on this, as does the
     // type inference code below in this function.
     if (hasI64Arg || fi.sig().ret() == ExprType::I64)
         return true;
@@ -606,17 +606,17 @@ Instance::callExport(JSContext* cx, uint
         v = i < args.length() ? args[i] : UndefinedValue();
         switch (func.sig().arg(i)) {
           case ValType::I32:
             if (!ToInt32(cx, v, (int32_t*)&exportArgs[i]))
                 return false;
             break;
           case ValType::I64:
             if (!JitOptions.wasmTestMode) {
-                JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64);
+                JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64_TYPE);
                 return false;
             }
             if (!ReadI64Object(cx, v, (int64_t*)&exportArgs[i]))
                 return false;
             break;
           case ValType::F32:
             if (JitOptions.wasmTestMode && v.isObject()) {
                 if (!ReadCustomFloat32NaNObject(cx, v, (uint32_t*)&exportArgs[i]))
@@ -717,17 +717,17 @@ Instance::callExport(JSContext* cx, uint
       case ExprType::Void:
         args.rval().set(UndefinedValue());
         break;
       case ExprType::I32:
         args.rval().set(Int32Value(*(int32_t*)retAddr));
         break;
       case ExprType::I64:
         if (!JitOptions.wasmTestMode) {
-            JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64);
+            JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64_TYPE);
             return false;
         }
         retObj = CreateI64Object(cx, *(int64_t*)retAddr);
         if (!retObj)
             return false;
         break;
       case ExprType::F32:
         if (JitOptions.wasmTestMode && IsNaN(*(float*)retAddr)) {
--- a/js/src/wasm/WasmJS.cpp
+++ b/js/src/wasm/WasmJS.cpp
@@ -283,17 +283,20 @@ GetImports(JSContext* cx,
                     return ThrowBadImportType(cx, import.field.get(), "Number");
                 int32_t i32;
                 if (!ToInt32(cx, v, &i32))
                     return false;
                 val = Val(uint32_t(i32));
                 break;
               }
               case ValType::I64: {
-                MOZ_ASSERT(JitOptions.wasmTestMode, "no int64 in JS");
+                if (!JitOptions.wasmTestMode) {
+                    JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64_LINK);
+                    return false;
+                }
                 int64_t i64;
                 if (!ReadI64Object(cx, v, &i64))
                     return false;
                 val = Val(uint64_t(i64));
                 break;
               }
               case ValType::F32: {
                 if (JitOptions.wasmTestMode && v.isObject()) {
--- a/js/src/wasm/WasmModule.cpp
+++ b/js/src/wasm/WasmModule.cpp
@@ -1014,17 +1014,20 @@ GetGlobalExport(JSContext* cx, const Glo
     }
 
     switch (global.type()) {
       case ValType::I32: {
         jsval.set(Int32Value(val.i32()));
         return true;
       }
       case ValType::I64: {
-        MOZ_ASSERT(JitOptions.wasmTestMode, "no int64 in asm.js/wasm");
+        if (!JitOptions.wasmTestMode) {
+            JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64_LINK);
+            return false;
+        }
         RootedObject obj(cx, CreateI64Object(cx, val.i64()));
         if (!obj)
             return false;
         jsval.set(ObjectValue(*obj));
         return true;
       }
       case ValType::F32: {
         float f = val.f32();
--- a/js/src/wasm/WasmValidate.cpp
+++ b/js/src/wasm/WasmValidate.cpp
@@ -923,20 +923,17 @@ DecodeTableLimits(Decoder& d, TableDescV
 
 static bool
 GlobalIsJSCompatible(Decoder& d, ValType type, bool isMutable)
 {
     switch (type) {
       case ValType::I32:
       case ValType::F32:
       case ValType::F64:
-        break;
       case ValType::I64:
-        if (!jit::JitOptions.wasmTestMode)
-            return d.fail("can't import/export an Int64 global to JS");
         break;
       default:
         return d.fail("unexpected variable type in global import/export");
     }
 
     if (isMutable)
         return d.fail("can't import/export mutable globals in the MVP");