Old SGI-hacker-me is on board with spec'ing as-is. Thanks, /be
On Mar 26, 2013, at 7:02 PM, Kenneth Russell <k...@google.com> wrote: > Dmitry, thank you for prototyping and benchmarking this. There should > be no question that a slowdown of 25% is too high a cost to pay. > > Allen's analysis earlier in the thread indicates that no spec changes > are necessary in order to allow multiple bit patterns to be used when > storing NaNs into Float32Array and Float64Array. Can this topic be > laid to rest? > > -Ken > > > > On Tue, Mar 26, 2013 at 12:14 PM, Dmitry Lomov <dslo...@google.com> wrote: >> 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 <al...@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 >>> >>> rawValue is interpreted, taking into accont the value of isBigEndian, as >>> a bit string encoding of an IEEE 754-208 binary64 value. >>> If rawValue is any an IEEE 754-208 binary64 NaN value, return the NaN >>> Number value. >>> 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 >>> >>> 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@mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss@mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> _______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss