Bug 1415224: Remove wasm testing mode for custom NaN payloads; r=luke
authorBenjamin Bouvier <benj@benj.me>
Tue, 07 Nov 2017 19:16:39 +0100
changeset 436460 ff37d9f812becdce7d40c24fe4b319f1fc8413e7
parent 436459 75c9879941ee6187423df2158739d20e37e40a05
child 436461 bcae00340c54b778b9ddc0393edbdb7e44c23447
push id117
push userfmarier@mozilla.com
push dateTue, 28 Nov 2017 20:17:16 +0000
reviewersluke
bugs1415224
milestone59.0a1
Bug 1415224: Remove wasm testing mode for custom NaN payloads; r=luke MozReview-Commit-ID: 1CB9zUkTIyk
js/src/jit-test/lib/wasm.js
js/src/jit-test/tests/wasm/nan-semantics.js
js/src/jit/arm/Simulator-arm.cpp
js/src/wasm/WasmInstance.cpp
js/src/wasm/WasmJS.cpp
js/src/wasm/WasmJS.h
js/src/wasm/WasmModule.cpp
--- a/js/src/jit-test/lib/wasm.js
+++ b/js/src/jit-test/lib/wasm.js
@@ -45,16 +45,59 @@ function jsify(wasmVal) {
         return Infinity;
     if (wasmVal === '-infinity')
         return Infinity;
     if (wasmVal === '-0')
         return -0;
     return wasmVal;
 }
 
+function makeF32Assert(i, func, expected, params=[]) {
+    return `
+    (func (export "assert_${i}") (result i32)
+     ${ params.join('\n') }
+     call ${func}
+     i32.reinterpret/f32
+     i32.const ${expected}
+     i32.eq
+    )`;
+}
+
+function makeF64Assert(i, func, expected, params=[]) {
+    return `
+    (func (export "assert_${i}") (result i32)
+     ${ params.join('\n') }
+     call ${func}
+     i64.reinterpret/f64
+     i64.const ${expected}
+     i64.eq
+    )`;
+}
+
+function wasmAssert(src, assertions) {
+    let newSrc = src.substr(0, src.lastIndexOf(')'));
+    let i = 0;
+    for (let a of assertions) {
+        if (a.type === 'f32')
+            newSrc += makeF32Assert(i++, a.func, a.expected, a.params);
+        if (a.type === 'f64')
+            newSrc += makeF64Assert(i++, a.func, a.expected, a.params);
+    }
+    newSrc += ')';
+
+    let { exports } = wasmEvalText(newSrc);
+
+    for (let j = 0; j < i; j++) {
+        let { func, expected, params } = assertions[j];
+        let paramText = params ? params.join(', ') : '';
+        assertEq(exports['assert_' + j](), 1,
+                 `Unexpected value when running ${func}(${paramText}), expecting ${expected}.`);
+    }
+}
+
 // Assert that the expected value is equal to the int64 value, as passed by
 // Baldr: {low: int32, high: int32}.
 // - if the expected value is in the int32 range, it can be just a number.
 // - otherwise, an object with the properties "high" and "low".
 function assertEqI64(observed, expect) {
     assertEq(typeof observed, 'object', "observed must be an i64 object");
     assertEq(typeof expect === 'object' || typeof expect === 'number', true,
              "expect must be an i64 object or number");
@@ -67,42 +110,16 @@ function assertEqI64(observed, expect) {
     } else {
         assertEq(typeof expect.low, 'number');
         assertEq(typeof expect.high, 'number');
         assertEq(low, expect.low | 0, "low 32 bits don't match");
         assertEq(high, expect.high | 0, "high 32 bits don't match");
     }
 }
 
-// Asserts in Baldr test mode that NaN payloads match.
-function assertEqNaN(x, y) {
-    if (typeof x === 'number') {
-        assertEq(Number.isNaN(x), Number.isNaN(y));
-        return;
-    }
-
-    assertEq(typeof x === 'object' &&
-             typeof x.nan_low === 'number',
-             true,
-             "assertEqNaN args must have shape {nan_high, nan_low}");
-
-    assertEq(typeof y === 'object' &&
-             typeof y.nan_low === 'number',
-             true,
-             "assertEqNaN args must have shape {nan_high, nan_low}");
-
-    assertEq(typeof x.nan_high,
-             typeof y.nan_high,
-             "both args must have nan_high, or none");
-
-    assertEq(x.nan_high, y.nan_high, "assertEqNaN nan_high don't match");
-    if (typeof x.nan_low !== 'undefined')
-        assertEq(x.nan_low, y.nan_low, "assertEqNaN nan_low don't match");
-}
-
 function createI64(val) {
     let ret;
     if (typeof val === 'number') {
         assertEq(val, val|0, "number input to createI64 must be an int32");
         ret = {
             low: val,
             high: val < 0 ? -1 : 0 // sign extension
         };
--- a/js/src/jit-test/tests/wasm/nan-semantics.js
+++ b/js/src/jit-test/tests/wasm/nan-semantics.js
@@ -31,145 +31,145 @@ wasmEvalText('(module (import "" "float3
 
 f64[0] = NaN;
 f64[0] = f64[0]; // Force canonicalization.
 f64[1] = wasmEvalText('(module (func (result f64) (f64.const nan:0x123456)) (export "" 0))').exports[""]();
 assertSameBitPattern(0, 8, 8);
 
 wasmEvalText('(module (import "" "float64" (param f64)) (func (call 0 (f64.const nan:0x123456))) (export "" 0))', checkBitPatterns).exports[""]();
 
-// Enable test mode.
-setJitCompilerOption('wasm.test-mode', 1);
-
 // SANITY CHECKS
 
 // There are two kinds of NaNs: signaling and quiet. Usually, the first bit of
 // the payload is used to indicate whether it is quiet (1 for quiet, 0 for
 // signaling). Most operations have to transform a signaling NaN into a quiet
 // NaN, which prevents some optimizations in WebAssembly.
 
 // A float32 has 32 bits, 23 bits of them being reserved for the mantissa
 // (= NaN payload).
-var f32_nan_base = 0x7f800000;
-
+var f32_qnan_code = '(f32.const nan:0x600000)';
 var f32_snan_code = '(f32.const nan:0x200000)';
-var f32_snan = wasmEvalText(`(module (func (result f32) ${f32_snan_code}) (export "" 0))`).exports[""]();
-assertEqNaN(f32_snan, { nan_low: f32_nan_base | 0x200000 });
 
-var f32_qnan_code = '(f32.const nan:0x600000)';
-var f32_qnan = wasmEvalText(`(module (func (result f32) ${f32_qnan_code}) (export "" 0))`).exports[""]();
-assertEqNaN(f32_qnan, { nan_low: f32_nan_base | 0x600000 });
+var f32_snan = '0x7fa00000';
+var f32_qnan = '0x7fe00000';
 
 // A float64 has 64 bits, 1 for the sign, 11 for the exponent, the rest for the
 // mantissa (payload).
 var f64_nan_base_high = 0x7ff00000;
 
 var f64_snan_code = '(f64.const nan:0x4000000000000)';
-var f64_snan = wasmEvalText(`(module (func (result f64) ${f64_snan_code}) (export "" 0))`).exports[""]();
-assertEqNaN(f64_snan, { nan_low: 0x0, nan_high: f64_nan_base_high | 0x40000 });
+var f64_qnan_code = '(f64.const nan:0xc000000000000)';
+
+var f64_snan = '0x7ff4000000000000';
+var f64_qnan = '0x7ffc000000000000';
 
-var f64_qnan_code = '(f64.const nan:0xc000000000000)';
-var f64_qnan = wasmEvalText(`(module (func (result f64) ${f64_qnan_code}) (export "" 0))`).exports[""]();
-assertEqNaN(f64_qnan, { nan_low: 0x0, nan_high: f64_nan_base_high | 0xc0000 });
+wasmAssert(`(module
+    (func $f32_snan (result f32) ${f32_snan_code})
+    (func $f32_qnan (result f32) ${f32_qnan_code})
+    (func $f64_snan (result f64) ${f64_snan_code})
+    (func $f64_qnan (result f64) ${f64_qnan_code})
+)`, [
+    { type: 'f32', func: '$f32_snan', expected: f32_snan },
+    { type: 'f32', func: '$f32_qnan', expected: f32_qnan },
+    { type: 'f64', func: '$f64_snan', expected: f64_snan },
+    { type: 'f64', func: '$f64_qnan', expected: f64_qnan },
+]);
 
 // Actual tests.
 
-// An example where a signaling nan gets transformed into a quiet nan:
-// snan + 0.0 = qnan
-var nan = wasmEvalText(`(module (func (result f32) (f32.add ${f32_snan_code} (f32.const 0))) (export "" 0))`).exports[""]();
-assertEqNaN(nan, f32_qnan);
+wasmAssert(`(module
+    (global (mut f32) (f32.const 0))
+    (global (mut f64) (f64.const 0))
 
-// Globals.
-var m = wasmEvalText(`(module
-    (import "globals" "x" (global f32))
-    (func (result f32) (get_global 0))
-    (export "global" global 0)
-    (export "test" 0))
-`, { globals: { x: f32_snan } }).exports;
+    ;; An example where a signaling nan gets transformed into a quiet nan:
+    ;; snan + 0.0 = qnan
+    (func $add (result f32) (f32.add ${f32_snan_code} (f32.const 0)))
 
-assertEqNaN(m.test(), f32_snan);
-assertEqNaN(m.global, f32_snan);
+    ;; Shouldn't affect NaNess.
+    (func $set_get_global_f32 (result f32)
+        ${f32_snan_code}
+        set_global 0
+        get_global 0
+    )
 
-var m = wasmEvalText(`(module
-    (import "globals" "x" (global f64))
-    (func (result f64) (get_global 0))
-    (export "global" global 0)
-    (export "test" 0))
-`, { globals: { x: f64_snan } }).exports;
-
-assertEqNaN(m.test(), f64_snan);
-assertEqNaN(m.global, f64_snan);
+    ;; Shouldn't affect NaNess.
+    (func $set_get_global_f64 (result f64)
+        ${f64_snan_code}
+        set_global 1
+        get_global 1
+    )
+)`, [
+    { type: 'f32', func: '$add', expected: f32_qnan },
+    { type: 'f32', func: '$set_get_global_f32', expected: f32_snan },
+    { type: 'f64', func: '$set_get_global_f64', expected: f64_snan },
+]);
 
 // NaN propagation behavior.
-var constantCache = new Map;
-function getConstant(code) {
-    if (typeof code === 'number')
-        return code;
-    if (constantCache.has(code)) {
-        return constantCache.get(code);
-    }
-    let type = code.indexOf('f32') >= 0 ? 'f32' : 'f64';
-    let val = wasmEvalText(`(module (func (result ${type}) ${code}) (export "" 0))`).exports[""]();
-    constantCache.set(code, val);
-    return val;
-}
+function test(type, opcode, lhs_code, rhs_code) {
+    let qnan_code = type === 'f32' ? f32_qnan : f64_qnan;
 
-function test(type, opcode, snan_code, rhs_code, qnan_val) {
-    var snan_val = getConstant(snan_code);
-    var rhs = getConstant(rhs_code);
+    let t = type;
+    let op = opcode;
 
     // Test all forms:
     // - (constant, constant),
     // - (constant, variable),
     // - (variable, constant),
     // - (variable, variable)
-    assertEqNaN(wasmEvalText(`(module (func (result ${type}) (${type}.${opcode} ${snan_code} ${rhs_code})) (export "" 0))`).exports[""](), qnan_val);
-    assertEqNaN(wasmEvalText(`(module (func (param ${type}) (result ${type}) (${type}.${opcode} (get_local 0) ${rhs_code})) (export "" 0))`).exports[""](snan_val), qnan_val);
-    assertEqNaN(wasmEvalText(`(module (func (param ${type}) (result ${type}) (${type}.${opcode} ${snan_code} (get_local 0))) (export "" 0))`).exports[""](rhs), qnan_val);
-    assertEqNaN(wasmEvalText(`(module (func (param ${type}) (param ${type}) (result ${type}) (${type}.${opcode} (get_local 0) (get_local 1))) (export "" 0))`).exports[""](snan_val, rhs), qnan_val);
+    wasmAssert(`(module
+        (func $1 (result ${t}) (${t}.${op} ${lhs_code} ${rhs_code}))
+        (func $2 (param ${t}) (result ${t}) (${t}.${op} (get_local 0) ${rhs_code}))
+        (func $3 (param ${t}) (result ${t}) (${t}.${op} ${lhs_code} (get_local 0)))
+        (func $4 (param ${t}) (param ${t}) (result ${t}) (${t}.${op} (get_local 0) (get_local 1)))
+    )`, [
+        { type, func: '$1', expected: qnan_code },
+        { type, func: '$2', params: [lhs_code], expected: qnan_code },
+        { type, func: '$3', params: [rhs_code], expected: qnan_code },
+        { type, func: '$4', params: [lhs_code, rhs_code], expected: qnan_code },
+    ]);
 }
 
 var f32_zero = '(f32.const 0)';
 var f64_zero = '(f64.const 0)';
 
 var f32_one = '(f32.const 1)';
 var f64_one = '(f64.const 1)';
 
 var f32_negone = '(f32.const -1)';
 var f64_negone = '(f64.const -1)';
 
 // x - 0.0 doesn't get folded into x:
-test('f32', 'sub', f32_snan_code, f32_zero, f32_qnan);
-test('f64', 'sub', f64_snan_code, f64_zero, f64_qnan);
+test('f32', 'sub', f32_snan_code, f32_zero);
+test('f64', 'sub', f64_snan_code, f64_zero);
 
 // x * 1.0 doesn't get folded into x:
-test('f32', 'mul', f32_snan_code, f32_one, f32_qnan);
-test('f32', 'mul', f32_one, f32_snan_code, f32_qnan);
+test('f32', 'mul', f32_snan_code, f32_one);
+test('f32', 'mul', f32_one, f32_snan_code);
 
-test('f64', 'mul', f64_snan_code, f64_one, f64_qnan);
-test('f64', 'mul', f64_one, f64_snan_code, f64_qnan);
+test('f64', 'mul', f64_snan_code, f64_one);
+test('f64', 'mul', f64_one, f64_snan_code);
 
 // x * -1.0 doesn't get folded into -x:
-test('f32', 'mul', f32_snan_code, f32_negone, f32_qnan);
-test('f32', 'mul', f32_negone, f32_snan_code, f32_qnan);
+test('f32', 'mul', f32_snan_code, f32_negone);
+test('f32', 'mul', f32_negone, f32_snan_code);
 
-test('f64', 'mul', f64_snan_code, f64_negone, f64_qnan);
-test('f64', 'mul', f64_negone, f64_snan_code, f64_qnan);
+test('f64', 'mul', f64_snan_code, f64_negone);
+test('f64', 'mul', f64_negone, f64_snan_code);
 
 // x / -1.0 doesn't get folded into -1 * x:
-test('f32', 'div', f32_snan_code, f32_negone, f32_qnan);
-test('f64', 'div', f64_snan_code, f64_negone, f64_qnan);
+test('f32', 'div', f32_snan_code, f32_negone);
+test('f64', 'div', f64_snan_code, f64_negone);
 
 // min doesn't get folded when one of the operands is a NaN
-test('f32', 'min', f32_snan_code, f32_zero, f32_qnan);
-test('f32', 'min', f32_zero, f32_snan_code, f32_qnan);
+test('f32', 'min', f32_snan_code, f32_zero);
+test('f32', 'min', f32_zero, f32_snan_code);
 
-test('f64', 'min', f64_snan_code, f64_zero, f64_qnan);
-test('f64', 'min', f64_zero, f64_snan_code, f64_qnan);
+test('f64', 'min', f64_snan_code, f64_zero);
+test('f64', 'min', f64_zero, f64_snan_code);
 
 // ditto for max
-test('f32', 'max', f32_snan_code, f32_zero, f32_qnan);
-test('f32', 'max', f32_zero, f32_snan_code, f32_qnan);
+test('f32', 'max', f32_snan_code, f32_zero);
+test('f32', 'max', f32_zero, f32_snan_code);
 
-test('f64', 'max', f64_snan_code, f64_zero, f64_qnan);
-test('f64', 'max', f64_zero, f64_snan_code, f64_qnan);
+test('f64', 'max', f64_snan_code, f64_zero);
+test('f64', 'max', f64_zero, f64_snan_code);
 
 setJitCompilerOption('wasm.test-mode', 0);
--- a/js/src/jit/arm/Simulator-arm.cpp
+++ b/js/src/jit/arm/Simulator-arm.cpp
@@ -2869,24 +2869,24 @@ Simulator::softwareInterrupt(SimInstruct
         }
       }
     }
 }
 
 void
 Simulator::canonicalizeNaN(double* value)
 {
-    if (!JitOptions.wasmTestMode && FPSCR_default_NaN_mode_)
+    if (!wasm::CodeExists && !wasm::LookupCodeSegment(get_pc_as<void*>()) && FPSCR_default_NaN_mode_)
         *value = JS::CanonicalizeNaN(*value);
 }
 
 void
 Simulator::canonicalizeNaN(float* value)
 {
-    if (!JitOptions.wasmTestMode && FPSCR_default_NaN_mode_)
+    if (!wasm::CodeExists && !wasm::LookupCodeSegment(get_pc_as<void*>()) && FPSCR_default_NaN_mode_)
         *value = JS::CanonicalizeNaN(*value);
 }
 
 // Stop helper functions.
 bool
 Simulator::isStopInstruction(SimInstruction* instr)
 {
     return (instr->bits(27, 24) == 0xF) && (instr->svcValue() >= kStopCode);
--- a/js/src/wasm/WasmInstance.cpp
+++ b/js/src/wasm/WasmInstance.cpp
@@ -610,30 +610,20 @@ Instance::callExport(JSContext* cx, uint
                 return false;
             break;
           case ValType::I64:
             MOZ_ASSERT(JitOptions.wasmTestMode);
             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]))
-                    return false;
-                break;
-            }
             if (!RoundFloat32(cx, v, (float*)&exportArgs[i]))
                 return false;
             break;
           case ValType::F64:
-            if (JitOptions.wasmTestMode && v.isObject()) {
-                if (!ReadCustomDoubleNaNObject(cx, v, (uint64_t*)&exportArgs[i]))
-                    return false;
-                break;
-            }
             if (!ToNumber(cx, v, (double*)&exportArgs[i]))
                 return false;
             break;
           case ValType::I8x16: {
             SimdConstant simd;
             if (!ToSimdConstant<Int8x16>(cx, v, &simd))
                 return false;
             memcpy(&exportArgs[i], simd.asInt8x16(), Simd128DataSize);
@@ -719,31 +709,19 @@ Instance::callExport(JSContext* cx, uint
         break;
       case ExprType::I64:
         MOZ_ASSERT(JitOptions.wasmTestMode);
         retObj = CreateI64Object(cx, *(int64_t*)retAddr);
         if (!retObj)
             return false;
         break;
       case ExprType::F32:
-        if (JitOptions.wasmTestMode && IsNaN(*(float*)retAddr)) {
-            retObj = CreateCustomNaNObject(cx, (float*)retAddr);
-            if (!retObj)
-                return false;
-            break;
-        }
         args.rval().set(NumberValue(*(float*)retAddr));
         break;
       case ExprType::F64:
-        if (JitOptions.wasmTestMode && IsNaN(*(double*)retAddr)) {
-            retObj = CreateCustomNaNObject(cx, (double*)retAddr);
-            if (!retObj)
-                return false;
-            break;
-        }
         args.rval().set(NumberValue(*(double*)retAddr));
         break;
       case ExprType::I8x16:
         retObj = CreateSimd<Int8x16>(cx, (int8_t*)retAddr);
         if (!retObj)
             return false;
         break;
       case ExprType::I16x8:
--- a/js/src/wasm/WasmJS.cpp
+++ b/js/src/wasm/WasmJS.cpp
@@ -76,82 +76,16 @@ bool
 wasm::HasSupport(JSContext* cx)
 {
     return cx->options().wasm() && HasCompilerSupport(cx);
 }
 
 // ============================================================================
 // Imports
 
-template<typename T>
-JSObject*
-wasm::CreateCustomNaNObject(JSContext* cx, T* addr)
-{
-    MOZ_ASSERT(IsNaN(*addr));
-
-    RootedObject obj(cx, JS_NewPlainObject(cx));
-    if (!obj)
-        return nullptr;
-
-    int32_t* i32 = (int32_t*)addr;
-    RootedValue intVal(cx, Int32Value(i32[0]));
-    if (!JS_DefineProperty(cx, obj, "nan_low", intVal, JSPROP_ENUMERATE))
-        return nullptr;
-
-    if (IsSame<double, T>::value) {
-        intVal = Int32Value(i32[1]);
-        if (!JS_DefineProperty(cx, obj, "nan_high", intVal, JSPROP_ENUMERATE))
-            return nullptr;
-    }
-
-    return obj;
-}
-
-template JSObject* wasm::CreateCustomNaNObject(JSContext* cx, float* addr);
-template JSObject* wasm::CreateCustomNaNObject(JSContext* cx, double* addr);
-
-bool
-wasm::ReadCustomFloat32NaNObject(JSContext* cx, HandleValue v, uint32_t* ret)
-{
-    RootedObject obj(cx, &v.toObject());
-    RootedValue val(cx);
-
-    int32_t i32;
-    if (!JS_GetProperty(cx, obj, "nan_low", &val))
-        return false;
-    if (!ToInt32(cx, val, &i32))
-        return false;
-
-    *ret = i32;
-    return true;
-}
-
-bool
-wasm::ReadCustomDoubleNaNObject(JSContext* cx, HandleValue v, uint64_t* ret)
-{
-    RootedObject obj(cx, &v.toObject());
-    RootedValue val(cx);
-
-    int32_t i32;
-    if (!JS_GetProperty(cx, obj, "nan_high", &val))
-        return false;
-    if (!ToInt32(cx, val, &i32))
-        return false;
-    *ret = uint32_t(i32);
-    *ret <<= 32;
-
-    if (!JS_GetProperty(cx, obj, "nan_low", &val))
-        return false;
-    if (!ToInt32(cx, val, &i32))
-        return false;
-    *ret |= uint32_t(i32);
-
-    return true;
-}
-
 JSObject*
 wasm::CreateI64Object(JSContext* cx, int64_t i64)
 {
     RootedObject result(cx, JS_NewPlainObject(cx));
     if (!result)
         return nullptr;
 
     RootedValue val(cx, Int32Value(uint32_t(i64)));
@@ -294,43 +228,25 @@ GetImports(JSContext* cx,
                 }
                 int64_t i64;
                 if (!ReadI64Object(cx, v, &i64))
                     return false;
                 val = Val(uint64_t(i64));
                 break;
               }
               case ValType::F32: {
-                if (JitOptions.wasmTestMode && v.isObject()) {
-                    uint32_t bits;
-                    if (!ReadCustomFloat32NaNObject(cx, v, &bits))
-                        return false;
-                    float f;
-                    BitwiseCast(bits, &f);
-                    val = Val(f);
-                    break;
-                }
                 if (!v.isNumber())
                     return ThrowBadImportType(cx, import.field.get(), "Number");
                 double d;
                 if (!ToNumber(cx, v, &d))
                     return false;
                 val = Val(float(d));
                 break;
               }
               case ValType::F64: {
-                if (JitOptions.wasmTestMode && v.isObject()) {
-                    uint64_t bits;
-                    if (!ReadCustomDoubleNaNObject(cx, v, &bits))
-                        return false;
-                    double d;
-                    BitwiseCast(bits, &d);
-                    val = Val(d);
-                    break;
-                }
                 if (!v.isNumber())
                     return ThrowBadImportType(cx, import.field.get(), "Number");
                 double d;
                 if (!ToNumber(cx, v, &d))
                     return false;
                 val = Val(d);
                 break;
               }
--- a/js/src/wasm/WasmJS.h
+++ b/js/src/wasm/WasmJS.h
@@ -26,35 +26,16 @@
 namespace js {
 
 class TypedArrayObject;
 class WasmFunctionScope;
 class WasmInstanceScope;
 
 namespace wasm {
 
-// Creates a testing-only NaN JS object with fields as described above, for
-// T=float or T=double.
-
-template<typename T>
-JSObject*
-CreateCustomNaNObject(JSContext* cx, T* addr);
-
-// Converts a testing-only NaN JS object with a nan_low field to a float32 NaN
-// with nan_low as the payload.
-
-bool
-ReadCustomFloat32NaNObject(JSContext* cx, HandleValue v, uint32_t* ret);
-
-// Converts a testing-only NaN JS object with nan_{low,high} components to a
-// double NaN with nan_low|(nan_high)>>32 as the payload.
-
-bool
-ReadCustomDoubleNaNObject(JSContext* cx, HandleValue v, uint64_t* ret);
-
 // Creates a JS object containing two fields (low: low 32 bits; high: high 32
 // bits) of a given Int64 value. For testing purposes only.
 
 JSObject*
 CreateI64Object(JSContext* cx, int64_t i64);
 
 // Reads an int64 from a JS object with the same shape as described in the
 // comment above. For testing purposes only.
--- a/js/src/wasm/WasmModule.cpp
+++ b/js/src/wasm/WasmModule.cpp
@@ -1026,35 +1026,21 @@ GetGlobalExport(JSContext* cx, const Glo
         RootedObject obj(cx, CreateI64Object(cx, val.i64()));
         if (!obj)
             return false;
         jsval.set(ObjectValue(*obj));
         return true;
       }
       case ValType::F32: {
         float f = val.f32();
-        if (JitOptions.wasmTestMode && IsNaN(f)) {
-            RootedObject obj(cx, CreateCustomNaNObject(cx, &f));
-            if (!obj)
-                return false;
-            jsval.set(ObjectValue(*obj));
-            return true;
-        }
         jsval.set(DoubleValue(JS::CanonicalizeNaN(double(f))));
         return true;
       }
       case ValType::F64: {
         double d = val.f64();
-        if (JitOptions.wasmTestMode && IsNaN(d)) {
-            RootedObject obj(cx, CreateCustomNaNObject(cx, &d));
-            if (!obj)
-                return false;
-            jsval.set(ObjectValue(*obj));
-            return true;
-        }
         jsval.set(DoubleValue(JS::CanonicalizeNaN(d)));
         return true;
       }
       default: {
         break;
       }
     }
     MOZ_CRASH("unexpected type when creating global exports");