diff --git a/CHANGES.md b/CHANGES.md index e8bb3a5698..6393730c3b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -25,6 +25,7 @@ * Lib: make the Wasm version of Json.output work with native ints and JavaScript objects (#1872) * Compiler: static evaluation of more primitives (#1912) * Compiler: faster compilation by stopping sooner when optimizations become unproductive (#1939) +* Runtime: use Dataview to convert between floats and bit representation ## Bug fixes * Compiler: fix stack overflow issues with double translation (#1869) diff --git a/ECMASCRIPT.md b/ECMASCRIPT.md index 1aa48cfd82..839fce3b2b 100644 --- a/ECMASCRIPT.md +++ b/ECMASCRIPT.md @@ -56,6 +56,10 @@ Features are grouped by ECMAScript version. - [Compatibility](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap#browser_compatibility) +### DataView + +- [Compatibility](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView#browser_compatibility) + ## ECMAScript 2016 ### async function diff --git a/compiler/lib/reserved.ml b/compiler/lib/reserved.ml index 05d0995917..fde3acd8fe 100644 --- a/compiler/lib/reserved.ml +++ b/compiler/lib/reserved.ml @@ -144,6 +144,7 @@ let provided = ; "require" (* only available in node *) ; "Symbol" ; "ArrayBuffer" + ; "DataView" ; "Float32Array" ; "Float64Array" ; "Int16Array" diff --git a/compiler/tests-check-prim/main.4.14.output b/compiler/tests-check-prim/main.4.14.output index dd380a2fa2..cbfefa3a6f 100644 --- a/compiler/tests-check-prim/main.4.14.output +++ b/compiler/tests-check-prim/main.4.14.output @@ -91,6 +91,9 @@ caml_gr_text_size caml_gr_wait_event caml_gr_window_id +From +hash.js: +caml_hash_mix_int64 + From +ints.js: caml_div caml_mod diff --git a/compiler/tests-check-prim/main.5.2.output b/compiler/tests-check-prim/main.5.2.output index f89beb7774..6aff797f81 100644 --- a/compiler/tests-check-prim/main.5.2.output +++ b/compiler/tests-check-prim/main.5.2.output @@ -87,6 +87,9 @@ caml_gr_text_size caml_gr_wait_event caml_gr_window_id +From +hash.js: +caml_hash_mix_int64 + From +ints.js: caml_div caml_mod diff --git a/compiler/tests-check-prim/main.5.3.output b/compiler/tests-check-prim/main.5.3.output index d2184637ac..471517932a 100644 --- a/compiler/tests-check-prim/main.5.3.output +++ b/compiler/tests-check-prim/main.5.3.output @@ -86,6 +86,9 @@ caml_gr_text_size caml_gr_wait_event caml_gr_window_id +From +hash.js: +caml_hash_mix_int64 + From +ints.js: caml_div caml_mod diff --git a/compiler/tests-check-prim/unix-Unix.4.14.output b/compiler/tests-check-prim/unix-Unix.4.14.output index e0ddc0dac5..c6bbcdf91f 100644 --- a/compiler/tests-check-prim/unix-Unix.4.14.output +++ b/compiler/tests-check-prim/unix-Unix.4.14.output @@ -167,6 +167,9 @@ caml_gr_text_size caml_gr_wait_event caml_gr_window_id +From +hash.js: +caml_hash_mix_int64 + From +ints.js: caml_div caml_mod diff --git a/compiler/tests-check-prim/unix-Unix.5.2.output b/compiler/tests-check-prim/unix-Unix.5.2.output index 1084d9a96f..6e1c8ba8e5 100644 --- a/compiler/tests-check-prim/unix-Unix.5.2.output +++ b/compiler/tests-check-prim/unix-Unix.5.2.output @@ -163,6 +163,9 @@ caml_gr_text_size caml_gr_wait_event caml_gr_window_id +From +hash.js: +caml_hash_mix_int64 + From +ints.js: caml_div caml_mod diff --git a/compiler/tests-check-prim/unix-Unix.5.3.output b/compiler/tests-check-prim/unix-Unix.5.3.output index c4a656b325..df95281669 100644 --- a/compiler/tests-check-prim/unix-Unix.5.3.output +++ b/compiler/tests-check-prim/unix-Unix.5.3.output @@ -162,6 +162,9 @@ caml_gr_text_size caml_gr_wait_event caml_gr_window_id +From +hash.js: +caml_hash_mix_int64 + From +ints.js: caml_div caml_mod diff --git a/compiler/tests-check-prim/unix-Win32.4.14.output b/compiler/tests-check-prim/unix-Win32.4.14.output index 2bc200a97d..dd90ad4b34 100644 --- a/compiler/tests-check-prim/unix-Win32.4.14.output +++ b/compiler/tests-check-prim/unix-Win32.4.14.output @@ -139,6 +139,9 @@ caml_gr_text_size caml_gr_wait_event caml_gr_window_id +From +hash.js: +caml_hash_mix_int64 + From +ints.js: caml_div caml_mod diff --git a/compiler/tests-check-prim/unix-Win32.5.2.output b/compiler/tests-check-prim/unix-Win32.5.2.output index 08d612f687..2cf4eaf5ac 100644 --- a/compiler/tests-check-prim/unix-Win32.5.2.output +++ b/compiler/tests-check-prim/unix-Win32.5.2.output @@ -136,6 +136,9 @@ caml_gr_text_size caml_gr_wait_event caml_gr_window_id +From +hash.js: +caml_hash_mix_int64 + From +ints.js: caml_div caml_mod diff --git a/compiler/tests-check-prim/unix-Win32.5.3.output b/compiler/tests-check-prim/unix-Win32.5.3.output index 7a05e69e21..8fc788cc78 100644 --- a/compiler/tests-check-prim/unix-Win32.5.3.output +++ b/compiler/tests-check-prim/unix-Win32.5.3.output @@ -135,6 +135,9 @@ caml_gr_text_size caml_gr_wait_event caml_gr_window_id +From +hash.js: +caml_hash_mix_int64 + From +ints.js: caml_div caml_mod diff --git a/runtime/js/hash.js b/runtime/js/hash.js index dcd9f9825f..ae19898dae 100644 --- a/runtime/js/hash.js +++ b/runtime/js/hash.js @@ -41,9 +41,26 @@ function caml_hash_mix_final(h) { } //Provides: caml_hash_mix_float -//Requires: caml_int64_bits_of_float, caml_hash_mix_int64 -function caml_hash_mix_float(h, v0) { - return caml_hash_mix_int64(h, caml_int64_bits_of_float(v0)); +//Requires: caml_int64_bits_of_float +//Requires: caml_hash_mix_int +//Requires: caml_int64_lo32, caml_int64_hi32 +function caml_hash_mix_float(hash, v0) { + var i64 = caml_int64_bits_of_float(v0); + var l = caml_int64_lo32(i64); + var h = caml_int64_hi32(i64); + /* Normalize NaNs */ + if ((h & 0x7ff00000) === 0x7ff00000 && (l | (h & 0xfffff)) !== 0) { + h = 0x7ff00000; + l = 0x00000001; + } else if (h === (0x80000000 | 0) && l === 0) { + /* Normalize -0 into +0 */ + // This code path is not used by caml_hash because 0 and -0 look + // like integers + h = 0; + } + hash = caml_hash_mix_int(hash, l); + hash = caml_hash_mix_int(hash, h); + return hash; } //Provides: caml_hash_mix_int64 //Requires: caml_hash_mix_int diff --git a/runtime/js/ieee_754.js b/runtime/js/ieee_754.js index 4a33608947..f0fc1cf124 100644 --- a/runtime/js/ieee_754.js +++ b/runtime/js/ieee_754.js @@ -17,74 +17,27 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -//Provides: jsoo_floor_log2 -var log2_ok = Math.log2 && Math.log2(1.1235582092889474e307) === 1020; -function jsoo_floor_log2(x) { - if (log2_ok) return Math.floor(Math.log2(x)); - var i = 0; - if (x === 0) return Number.NEGATIVE_INFINITY; - if (x >= 1) { - while (x >= 2) { - x /= 2; - i++; - } - } else { - while (x < 1) { - x *= 2; - i--; - } - } - return i; -} +//Provides: jsoo_dataview +var jsoo_dataview = new DataView(new ArrayBuffer(8)); //Provides: caml_int64_bits_of_float const -//Requires: jsoo_floor_log2, caml_int64_create_lo_mi_hi +//Requires: caml_int64_create_lo_mi_hi +//Requires: jsoo_dataview function caml_int64_bits_of_float(x) { - if (!Number.isFinite(x)) { - if (Number.isNaN(x)) return caml_int64_create_lo_mi_hi(1, 0, 0x7ff0); - if (x > 0) return caml_int64_create_lo_mi_hi(0, 0, 0x7ff0); - else return caml_int64_create_lo_mi_hi(0, 0, 0xfff0); - } - var sign = - x === 0 && 1 / x === Number.NEGATIVE_INFINITY - ? 0x8000 - : x >= 0 - ? 0 - : 0x8000; - if (sign) x = -x; - // Int64.bits_of_float 1.1235582092889474E+307 = 0x7fb0000000000000L - // using Math.LOG2E*Math.log(x) in place of Math.log2 result in precision lost - var exp = jsoo_floor_log2(x) + 1023; - if (exp <= 0) { - exp = 0; - x /= Math.pow(2, -1026); - } else { - x /= Math.pow(2, exp - 1027); - if (x < 16) { - x *= 2; - exp -= 1; - } - if (exp === 0) { - x /= 2; - } - } - var k = Math.pow(2, 24); - var r3 = x | 0; - x = (x - r3) * k; - var r2 = x | 0; - x = (x - r2) * k; - var r1 = x | 0; - r3 = (r3 & 0xf) | sign | (exp << 4); + jsoo_dataview.setFloat64(0, x, true); + var lo32 = jsoo_dataview.getUint32(0, true); + var hi32 = jsoo_dataview.getUint32(4, true); + var r1 = lo32 & 0xffffff; + var r2 = (lo32 >>> 24) | ((hi32 << 8) & 0xffffff); + var r3 = (hi32 >>> 16) & 0xffff; return caml_int64_create_lo_mi_hi(r1, r2, r3); } //Provides: caml_int32_bits_of_float const -//Requires: jsoo_floor_log2 +//Requires: jsoo_dataview function caml_int32_bits_of_float(x) { - var float32a = new Float32Array(1); - float32a[0] = x; - var int32a = new Int32Array(float32a.buffer); - return int32a[0] | 0; + jsoo_dataview.setFloat32(0, x, true); + return jsoo_dataview.getUint32(0, true) | 0; } //FP literals can be written using the hexadecimal @@ -150,24 +103,14 @@ function caml_hexstring_of_float(x, prec, style) { } //Provides: caml_int64_float_of_bits const +//Requires: jsoo_dataview function caml_int64_float_of_bits(x) { var lo = x.lo; var mi = x.mi; var hi = x.hi; - var exp = (hi & 0x7fff) >> 4; - if (exp === 2047) { - if ((lo | mi | (hi & 0xf)) === 0) - return hi & 0x8000 ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY; - else return Number.NaN; - } - var k = Math.pow(2, -24); - var res = (lo * k + mi) * k + (hi & 0xf); - if (exp > 0) { - res += 16; - res *= Math.pow(2, exp - 1027); - } else res *= Math.pow(2, -1026); - if (hi & 0x8000) res = -res; - return res; + jsoo_dataview.setUint32(0, lo | (mi << 24), true); + jsoo_dataview.setUint32(4, (mi >>> 8) | (hi << 16), true); + return jsoo_dataview.getFloat64(0, true); } //Provides: caml_nextafter_float const @@ -192,11 +135,10 @@ function caml_trunc_float(x) { } //Provides: caml_int32_float_of_bits const +//Requires: jsoo_dataview function caml_int32_float_of_bits(x) { - var int32a = new Int32Array(1); - int32a[0] = x; - var float32a = new Float32Array(int32a.buffer); - return float32a[0]; + jsoo_dataview.setUint32(0, x, true); + return jsoo_dataview.getFloat32(0, true); } //Provides: caml_classify_float const @@ -244,12 +186,11 @@ function caml_ldexp_float(x, exp) { return x; } //Provides: caml_frexp_float const -//Requires: jsoo_floor_log2 function caml_frexp_float(x) { if (x === 0 || !Number.isFinite(x)) return [0, x, 0]; var neg = x < 0; if (neg) x = -x; - var exp = Math.max(-1023, jsoo_floor_log2(x) + 1); + var exp = Math.max(-1023, Math.floor(Math.log2(x)) + 1); x *= Math.pow(2, -exp); while (x < 0.5) { x *= 2; @@ -482,7 +423,7 @@ function caml_fma_float(x, y, z) { } //Provides: caml_format_float const -//Requires: caml_parse_format, caml_finish_formatting +//Requires: caml_str_repeat, caml_parse_format, caml_finish_formatting function caml_format_float(fmt, x) { function toFixed(x, dp) { if (Math.abs(x) < 1.0) { @@ -492,9 +433,9 @@ function caml_format_float(fmt, x) { if (e > 20) { e -= 20; x /= Math.pow(10, e); - x += new Array(e + 1).join("0"); + x += caml_str_repeat(e, "0"); if (dp > 0) { - x = x + "." + new Array(dp + 1).join("0"); + x = x + "." + caml_str_repeat(dp, "0"); } return x; } else return x.toFixed(dp); diff --git a/runtime/js/mlBytes.js b/runtime/js/mlBytes.js index 9e588d799d..fb9473db40 100644 --- a/runtime/js/mlBytes.js +++ b/runtime/js/mlBytes.js @@ -48,24 +48,7 @@ //Provides: caml_str_repeat function caml_str_repeat(n, s) { - if (n === 0) return ""; - if (s.repeat) { - return s.repeat(n); - } // ECMAscript 6 and Firefox 24+ - var r = "", - l = 0; - for (;;) { - if (n & 1) r += s; - n >>= 1; - if (n === 0) return r; - s += s; - l++; - if (l === 9) { - s.slice(0, 1); // flatten the string - // then, the flattening of the whole string will be faster, - // as it will be composed of larger pieces - } - } + return s.repeat(n); } //Provides: caml_subarray_to_jsbytes