diff --git a/js/src/asmjs/WasmInstance.cpp b/js/src/asmjs/WasmInstance.cpp index 3a5964ab2fb6..7f303723037a 100644 --- a/js/src/asmjs/WasmInstance.cpp +++ b/js/src/asmjs/WasmInstance.cpp @@ -505,8 +505,8 @@ Instance::memoryLength() const } template -static JSObject* -CreateCustomNaNObject(JSContext* cx, T* addr) +JSObject* +js::wasm::CreateCustomNaNObject(JSContext* cx, T* addr) { MOZ_ASSERT(IsNaN(*addr)); @@ -528,8 +528,11 @@ CreateCustomNaNObject(JSContext* cx, T* addr) return obj; } -static bool -ReadCustomFloat32NaNObject(JSContext* cx, HandleValue v, uint32_t* ret) +template JSObject* js::wasm::CreateCustomNaNObject(JSContext* cx, float* addr); +template JSObject* js::wasm::CreateCustomNaNObject(JSContext* cx, double* addr); + +bool +js::wasm::ReadCustomFloat32NaNObject(JSContext* cx, HandleValue v, uint32_t* ret) { RootedObject obj(cx, &v.toObject()); RootedValue val(cx); @@ -544,8 +547,8 @@ ReadCustomFloat32NaNObject(JSContext* cx, HandleValue v, uint32_t* ret) return true; } -static bool -ReadCustomDoubleNaNObject(JSContext* cx, HandleValue v, uint64_t* ret) +bool +js::wasm::ReadCustomDoubleNaNObject(JSContext* cx, HandleValue v, uint64_t* ret) { RootedObject obj(cx, &v.toObject()); RootedValue val(cx); diff --git a/js/src/asmjs/WasmInstance.h b/js/src/asmjs/WasmInstance.h index c2c0d1401076..bb3102ee08ae 100644 --- a/js/src/asmjs/WasmInstance.h +++ b/js/src/asmjs/WasmInstance.h @@ -139,6 +139,25 @@ class Instance typedef UniquePtr UniqueInstance; +// 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 testing-only NaN JS object with fields as described above, for +// T=float or T=double. + +template +JSObject* +CreateCustomNaNObject(JSContext* cx, T* addr); + } // namespace wasm } // namespace js diff --git a/js/src/asmjs/WasmIonCompile.cpp b/js/src/asmjs/WasmIonCompile.cpp index 68f441888a52..f06b6ce3bcc3 100644 --- a/js/src/asmjs/WasmIonCompile.cpp +++ b/js/src/asmjs/WasmIonCompile.cpp @@ -2027,10 +2027,10 @@ EmitGetGlobal(FunctionCompiler& f) result = f.constant(int64_t(value.i64())); break; case ValType::F32: - result = f.constant(Float32Value(value.f32().fp()), mirType); + result = f.constant(value.f32()); break; case ValType::F64: - result = f.constant(DoubleValue(value.f64().fp()), mirType); + result = f.constant(value.f64()); break; case ValType::I8x16: result = f.constant(SimdConstant::CreateX16(value.i8x16()), mirType); diff --git a/js/src/asmjs/WasmJS.cpp b/js/src/asmjs/WasmJS.cpp index 15d3c77456ff..f5e2ae8ba8c7 100644 --- a/js/src/asmjs/WasmJS.cpp +++ b/js/src/asmjs/WasmJS.cpp @@ -161,6 +161,13 @@ GetImports(JSContext* cx, break; } case ValType::F32: { + if (JitOptions.wasmTestMode && v.isObject()) { + uint32_t bits; + if (!ReadCustomFloat32NaNObject(cx, v, &bits)) + return false; + val = Val(RawF32::fromBits(bits)); + break; + } double d; if (!ToNumber(cx, v, &d)) return false; @@ -168,6 +175,13 @@ GetImports(JSContext* cx, break; } case ValType::F64: { + if (JitOptions.wasmTestMode && v.isObject()) { + uint64_t bits; + if (!ReadCustomDoubleNaNObject(cx, v, &bits)) + return false; + val = Val(RawF64::fromBits(bits)); + break; + } double d; if (!ToNumber(cx, v, &d)) return false; diff --git a/js/src/asmjs/WasmModule.cpp b/js/src/asmjs/WasmModule.cpp index f920862c4876..7158a65a811a 100644 --- a/js/src/asmjs/WasmModule.cpp +++ b/js/src/asmjs/WasmModule.cpp @@ -714,11 +714,29 @@ GetGlobalExport(JSContext* cx, const GlobalDescVector& globals, uint32_t globalI return true; } case ValType::F32: { - jsval.set(DoubleValue(double(val.f32().fp()))); + float f = val.f32().fp(); + if (JitOptions.wasmTestMode && IsNaN(f)) { + uint32_t bits = val.f32().bits(); + RootedObject obj(cx, CreateCustomNaNObject(cx, (float*)&bits)); + if (!obj) + return false; + jsval.set(ObjectValue(*obj)); + return true; + } + jsval.set(DoubleValue(double(f))); return true; } case ValType::F64: { - jsval.set(DoubleValue(val.f64().fp())); + double d = val.f64().fp(); + if (JitOptions.wasmTestMode && IsNaN(d)) { + uint64_t bits = val.f64().bits(); + RootedObject obj(cx, CreateCustomNaNObject(cx, (double*)&bits)); + if (!obj) + return false; + jsval.set(ObjectValue(*obj)); + return true; + } + jsval.set(DoubleValue(d)); return true; } default: {