Re: Observability of NaN distinctions — is this a concern?

Dmitry Lomov dslomov at google.com
Tue Mar 26 12:14:14 PDT 2013


I would like to add some perf numbers to this discussion, if I may.

I have implemented a quick patch for V8 that implements NaN normalization
on Float64Array store. V8 does not use NaN boxing, so from implementation
perspective NaN normalization is not required by V8.

In my test, the perf penalty for Float64Array store is 25% (on ia32
architecture in optimized regime, using sse2 instructions).
I am attaching the test and my patch for your perusal (the patch should
easily apply to v8's bleeding_edge).

It feels like the performance hit is a very considerable factor here,
especially given that typed arrays are all about fast math.


Results on my machine:

Normalized stores:
$ ./out/ia32.release/d8 float-array.js
Start
14033 msec
Start
14059 msec
Start
13983 msec
Start
13979 msec
Non-normalized stores:
$ ./out.baseline/ia32.release/d8 float-array.js
Start
11197 msec
Start
11207 msec
Start
11207 msec
Start
11253 msec

Dmitry



On Tue, Mar 26, 2013 at 7:55 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:

>
> On Mar 26, 2013, at 1:29 AM, Oliver Hunt wrote:
>
>
> Ok, I'll try to go over this again, because for whatever reason it doesn't
> appear to stick:
>
> If you have a double-typed array, and access a member:
> typedArray[0]
>
> Then in ES it is a double that can be one of these values: +Infinitity,
> -Infinity, NaN, or a discrete value representable in IEEE double spec.
>  There are no signaling NaNs, nor is there any exposure of what the
> underlying bit pattern of the NaN is.
>
> So the runtime loads this double, and then stores it somewhere, anywhere,
> it doesn't matter where, eg.
> var tmp = typedArray[0];
>
> Now you store it:
> typedArray[whatever] = tmp;
>
> The specification must allow a bitwise comparison of typedArray[whatever]
> to typedArray[0] to return false, as it is not possible for any NaN-boxing
> engine to maintain the bit equality that you would otherwise desire, as
> that would be trivially exploitable.  When I say security and correctness i
> mean it in the "can't be remotely pwned" sense.
>
> Given that we can't guarantee that the bit pattern will remain unchanged
> the spec should mandate normalizing to the non-signalling NaN.
>
> --Oliver
>
>
> Oliver,
>
> Let's look at actual ES6 spec. language and see if there is actually
> anything you would like to see changed.  The encoding of NaNs is only
> discussed in three places:
>
> Section 8.1.5, first paragraph says:
>
> The Number type has exactly 18437736874454810627 (that is, 264253+3)
> values, representing the double-precision 64-bit format IEEE 754 values as
> specified in the IEEE Standard for Binary Floating-Point Arithmetic, except
> that the 9007199254740990 (that is, 2532) distinct “Not-a-Number” values
> of the IEEE Standard are represented in ECMAScript as a single special *
> NaN* value. (Note that the *NaN* value is produced by the program
> expression *NaN*.) In some implementations, external code might be able
> to detect a difference between various Not-a-Number values, but such
> behaviour is implementation-dependent; to ECMAScript code, all NaN values
> are indistinguishable from each other.
> This is very old text, most of which dates to ES1. It is defining the ES
> Number type, which is an abstraction, not an actual bit-level encoding. To
> me it say these things:
>    1) Unlike the the IEEE 64-bit floating point type.  The ES Number type
> has only a single NaN value.
>    2) An implementations are free to internally encode the Number type any
> why it desires (as long is it observably conforms to all the requirements
> of section 8.1.5).
>    3) In particular, an implementation  might have multiple internal bit
> patterns all of which correspond to the single NaN element of the Number
> type.
>    4) A corollary of 3) is that implementation are not required to
> internally canonicalize NaNs, that is an implementation level design
> decision.
>    5) Implementations are not required to canonicalize NaNs when they are
> passed or otherwise made visible to non-ES code.  Hence such code may be
> able to observe details of the NaN encoding, including whether or not a
> canonical NaN value is used internally by the ES implementation.
>
> Is there anything you think should change in the above specification text?
>
> Section 15.13.5.1.3 defines the GetValueFromBuffer abstraction operation
> which is currently the only place in the ES6 spec. where a ES Number value
> is retrieved from an ArrayBuffer. Step 8 of the specification algorithm is:
>
>    - 8 If *type* is “Float64” , then
>       1. * rawValue* is interpreted, taking into accont the value of *
>       isBigEndian*,  as a bit string encoding of an IEEE 754-208 binary64
>       value.
>       2. If *rawValue* is any an IEEE 754-208 binary64 NaN value, return
>       the *NaN* Number value.
>       3. Return the Number value that is encoded by *rawValue*.
>
> Step 7 is similar but deals with Float32 values.
>
> To me it say these things:
>    1) In all cases, an ES Number value (as defined in 8.1.5) is returned.
>    2) All IEEE NaN values are logically canonicalized as the single ES NaN
> value.
>    3) No additional requirements for ES Numbers, beyond those in 8.1.5 are
> introduced.  Actual representation remains up to implementation.
>
> Should anything change? If 8.1.5 continues to not mandate any particular
> or single encoding representation of a NaN, I don't see why this should
> either.
>
> Section 15.13.5.1.4 defines the SetValueInBuffer abstraction operation
> which is currently the only place in the ES6 spec. where a ES Number value
> is stored into a ArrayBuffer. Step 8 of the specification algorithm is:
>
>
>    - 8. Else, if *type* is “Float64” , then
>     1. Set *rawValue* to the 8 bytes that are the IEEE-868-2005 binary64
>       format encoding of *value*. If *isBigEndian* is *true*, the bytes
>       are arranged in big endian order.  Otherwise, the bytes are arranged in
>       little endian order.  If *value* is *NaN*, *rawValue* is may be set
>       to any implementation choosen non-signaling NaN encoding.
>
> Step 7 is similar but deals with Float32 values.
>
> To me it say these things:
>    1) When storing into an ArrayBuffer, canonicalization of ES NaN to some
> particular IEEE NaN is permitted but not required.
>    2) The actual ArrayBuffer bit-level representation of NaN values is
> completely implementation dependent.  It need not even be consistent across
> multiple stores. .
>    3) External observers of such a stored value may be able to detect NaN
> encoding differences by observing Numbers stored into ArrayBuffers.  This
> is allowed by 8.1.5
>    4) The actual encoding of a NaN value in an ArrayBuffer is observable
> by ES code by overly a non-float typed Array on an ArrayBuffer where a
> Number has been stored using the above steps.
>
> Point 4 seems to be in conflict with the 8.1.5 requirement "to ECMAScript
> code, all NaN values are indistinguishable from each other.".  However,
> consider that what is being observed is not directly an ES Number NaN value
> but instead a bit pattern that according to15.13.5.1.4 above may not be a
> direct reflection of the Number NaN that was stored. So maybe it slips by.
>
> So, again any change requests?
>
> From a spec. perspective we could require canonicalization to some
> specific IEEE NaN (how do we pick one?) in 15.13.5.4.  If we are going to
> do that, we presumably also should require canonicalization of endian-ness
> which is also observable and arguably a bigger interop hazard than NaNs.
>  However, I think the performance arguments for not canonicalizing
> endian-ness in typed array are stronger.  If we are going to continue to
>  let endian-ness be implementation determined then I don't think there is
> much point in worrying about changing the the handling of NaNs in
> 15.13.5.1.4. But, I'm flexible.
>
> Allen
>
>
>
>
>
>
>
>
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130326/ab829994/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: float-array.js
Type: application/x-javascript
Size: 697 bytes
Desc: not available
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130326/ab829994/attachment.js>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: normalized-store.patch
Type: application/octet-stream
Size: 954 bytes
Desc: not available
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130326/ab829994/attachment.obj>


More information about the es-discuss mailing list