diff --git a/js/src/jit/IonMacroAssembler.h b/js/src/jit/IonMacroAssembler.h index 283e25f354f5..d0a26ed2e03e 100644 --- a/js/src/jit/IonMacroAssembler.h +++ b/js/src/jit/IonMacroAssembler.h @@ -579,8 +579,12 @@ class MacroAssembler : public MacroAssemblerSpecific } } - template - void storeToTypedFloatArray(int arrayType, const S &value, const T &dest) { + template + void storeToTypedFloatArray(int arrayType, FloatRegister value, const T &dest) { +#ifdef JS_MORE_DETERMINISTIC + // See the comment in ToDoubleForTypedArray. + canonicalizeDouble(value); +#endif switch (arrayType) { case TypedArrayObject::TYPE_FLOAT32: convertDoubleToFloat(value, ScratchFloatReg); diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index 1e22432cde57..ad8c7a4287aa 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -1357,6 +1357,14 @@ js::ToDoubleForTypedArray(JSContext *cx, JS::HandleValue vp, double *d) *d = js_NaN; } +#ifdef JS_MORE_DETERMINISTIC + // It's possible to have a NaN value with the sign bit set. The spec allows + // this but it can confuse differential testing when this value is stored + // to a float array and then read back as integer. To work around this, we + // always canonicalize NaN values in more-deterministic builds. + *d = JS_CANONICALIZE_NAN(*d); +#endif + return true; }