Enable Wasm BigInt (#2643)

This enables WASM_BIGINT while maintaining (hypothetical) Safari 14 support
by shimming BigInt64Array and BigUint64Array if they are missing. I think the
last time we tried to enable WASM_BIGINT was before #2019 so our chances
are significantly better this time.

This will fix dynamic linking bugs and yields a minor reduction in code size.
This commit is contained in:
Hood Chatham 2022-06-02 10:09:54 -07:00 committed by GitHub
parent 0aafb5dd12
commit 95b1194945
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 152 additions and 9 deletions

View File

@ -90,6 +90,7 @@ export LDFLAGS_BASE=\
-std=c++14 \
-s LZ4=1 \
-L $(CPYTHONROOT)/installs/python-$(PYVERSION)/lib/ \
-s WASM_BIGINT \
$(EXTRA_LDFLAGS)
export CXXFLAGS_BASE=

View File

@ -113,6 +113,9 @@ substitutions:
Python rather than the host Python.
{pr}`2516`
- {{ Enhancement }} Pyodide now builds with `-sWASM_BIGINT`..
{pr}`2643`
### REPL
- {{ Enhancement }} Add a spinner while the REPL is loading

View File

@ -65,8 +65,8 @@ Pyodide,
| Browser | Minimal supported version | Release date |
| ------- | ------------------------- | ----------------- |
| Safari | 13.1 | 19 September 2019 |
| Edge | 80 | 26 Feb 2020 |
| Safari | 14.0 | 15 September 2020 |
| Edge | 80 | 26 February 2020 |
Other browsers with WebAssembly support might also work however they are not
officially supported.

View File

@ -1,7 +1,7 @@
From e83a295f8e1b8c48d4748d1811a4b22840f25e14 Mon Sep 17 00:00:00 2001
From: Hood <hood@mit.edu>
Date: Thu, 24 Jun 2021 04:08:02 -0700
Subject: [PATCH 1/7] Throw away errors in minify_wasm_js
Subject: [PATCH 1/6] Throw away errors in minify_wasm_js
---
emcc.py | 13 ++++++++-----

View File

@ -1,7 +1,7 @@
From 40956dee436737d9dd40e0b57c6e2ebd26569920 Mon Sep 17 00:00:00 2001
From: Hood <hood@mit.edu>
Date: Wed, 8 Sep 2021 17:49:15 -0700
Subject: [PATCH 2/7] Fix dup
Subject: [PATCH 2/6] Fix dup
This fixes two problems with the `dup` system calls:
1. `dup` expects that every file descriptor has a corresponding file (so pipes and (https://github.com/emscripten-core/emscripten/issues/14640)

View File

@ -1,7 +1,7 @@
From 73b89ee1b5a57c65824baf91b547be32b69decbd Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Tue, 15 Feb 2022 23:27:03 -0500
Subject: [PATCH 3/7] Fix side module exception handling
Subject: [PATCH 3/6] Fix side module exception handling
See https://github.com/emscripten-core/emscripten/pull/16309

View File

@ -1,7 +1,7 @@
From 8de43377d0e72a4c5794f8494a06d81a9609090f Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Wed, 2 Mar 2022 13:44:14 -0800
Subject: [PATCH 4/7] Fix lookupPath when applied to a symlink loop
Subject: [PATCH 4/6] Fix lookupPath when applied to a symlink loop
The following code leads to an infinite loop in lookupPath:

View File

@ -1,7 +1,7 @@
From 6aca63c041033835d08a99fb54b3327a36652ff8 Mon Sep 17 00:00:00 2001
From 8eed4062c1a0bd6aa7859938240f8761e6e72114 Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Wed, 18 May 2022 21:49:17 -0700
Subject: [PATCH 7/7] Indicate Emscripten version in uname
Subject: [PATCH 5/6] Indicate Emscripten version in uname
This patch has been upstreamed:
https://github.com/emscripten-core/emscripten/pull/17026

View File

@ -0,0 +1,139 @@
From 4462c2871933db0adc4b46a24f77b942caff969c Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Sun, 29 May 2022 18:17:29 -0700
Subject: [PATCH 6/6] Add BigInt64Array shim for Safari 14
---
src/parseTools.js | 2 +-
src/polyfill/bigint64array.js | 87 +++++++++++++++++++++++++++++++++++
src/preamble.js | 5 +-
3 files changed, 92 insertions(+), 2 deletions(-)
create mode 100644 src/polyfill/bigint64array.js
diff --git a/src/parseTools.js b/src/parseTools.js
index 92490fe71..8a183c610 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -94,7 +94,7 @@ function preprocess(text, filenameHint) {
showStack.push(truthy ? SHOW : IGNORE);
} else if (first === '#include') {
if (showCurrentLine()) {
- let filename = line.substr(line.indexOf(' ') + 1);
+ let filename = trimmed.substr(trimmed.indexOf(' ') + 1);
if (filename.startsWith('"')) {
filename = filename.substr(1, filename.length - 2);
}
diff --git a/src/polyfill/bigint64array.js b/src/polyfill/bigint64array.js
new file mode 100644
index 000000000..126c2b51f
--- /dev/null
+++ b/src/polyfill/bigint64array.js
@@ -0,0 +1,87 @@
+if (typeof BigInt64Array === "undefined") {
+ // BigInt64Array polyfill for Safari versions between v14.0 and v15.0.
+ // All browsers other than Safari added BigInt and BigInt64Array at the same
+ // time, but Safari introduced BigInt in v14.0 and introduced BigInt64Array in
+ // v15.0
+
+ function partsToBigIntSigned(lower, upper) {
+ return BigInt(lower) | (BigInt(upper + 2 * (upper & 0x80000000)) << BigInt(32));
+ }
+
+ function partsToBigIntUnsigned(lower, upper) {
+ return BigInt(lower) | (BigInt(upper) << BigInt(32));
+ }
+
+ function bigIntToParts(value) {
+ var lower = Number(BigInt(value) & BigInt(0xffffffff)) | 0;
+ var upper = (Number(BigInt(value) >> BigInt(32)) | 0);
+ return [lower, upper];
+ }
+
+ function createBigIntArrayShim(partsToBigInt) {
+ function createBigInt64Array(array) {
+ if(!ArrayBuffer.isView(array)){
+ array = new Uint32Array(array);
+ }
+ let proxy = new Proxy({
+ slice: function(min, max) {
+ var new_buf = array.slice(min * 2, max *2);
+ return createBigInt64Array(new_buf);
+ },
+ subarray: function(min, max) {
+ var new_buf = array.subarray(min * 2, max *2);
+ return createBigInt64Array(new_buf);
+ },
+ [Symbol.iterator]: function*() {
+ for (var i = 0; i < (array.length)/2; i++) {
+ yield partsToBigInt(array[2*i], array[2*i+1]);
+ }
+ },
+ buffer : array.buffer,
+ byteLength : array.byteLength,
+ offset : array.byteOffset / 2,
+ copyWithin: function(target, start, end) {
+ array.copyWithin(target*2, start * 2, end*2);
+ return proxy;
+ },
+ set: function(source, targetOffset) {
+ if(2*(source.length + targetOffset) > array.length) {
+ // This is the Chrome error message
+ // Firefox: "invalid or out-of-range index"
+ throw new RangeError("offset is out of bounds");
+ }
+ for (var i = 0; i < array.length; i++) {
+ var value = source[i];
+ var pair = bigIntToParts(BigInt(value));
+ array.set(pair, 2*(targetOffset + i));
+ }
+ }
+ }, {
+ get: function(target, idx, receiver) {
+ if (typeof idx !== "string" || !/^\d+$/.test(idx)) {
+ return Reflect.get(target, idx, receiver);
+ }
+ var lower = array[idx * 2];
+ var upper = array[idx * 2 + 1];
+ return partsToBigInt(lower, upper);
+ },
+ set: function(target, idx, value, receiver) {
+ if (typeof idx !== "string" || !/^\d+$/.test(idx)) {
+ return Reflect.set(target, idx, value, receiver);
+ }
+ if (typeof value !== "bigint") {
+ // Chrome error message, Firefox has no "a" in front if "BigInt".
+ throw new TypeError(`Cannot convert ${value} to a BigInt`);
+ }
+ var pair = bigIntToParts(value);
+ array.set(pair, 2*idx);
+ }
+ });
+ return proxy;
+ }
+ return createBigInt64Array;
+ }
+
+ var BigUint64Array = createBigIntArrayShim(partsToBigIntUnsigned);
+ var BigInt64Array = createBigIntArrayShim(partsToBigIntSigned);
+}
diff --git a/src/preamble.js b/src/preamble.js
index 1094dd7dc..6afca739b 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -285,9 +285,12 @@ function updateGlobalBufferAndViews(buf) {
Module['HEAPF32'] = HEAPF32 = new Float32Array(buf);
Module['HEAPF64'] = HEAPF64 = new Float64Array(buf);
#if WASM_BIGINT
+#if MIN_SAFARI_VERSION < 150000
+ #include "polyfill/bigint64array.js"
+#endif // MIN_SAFARI_VERSION < 15000
Module['HEAP64'] = HEAP64 = new BigInt64Array(buf);
Module['HEAPU64'] = HEAPU64 = new BigUint64Array(buf);
-#endif
+#endif // WASM_BIGINT
}
var TOTAL_STACK = {{{ TOTAL_STACK }}};
--
2.25.1

View File

@ -34,7 +34,7 @@
(BigInt(lower) | (BigInt(upper) << BigInt(32)))
#define IBIGINT_FROM_PAIR(lower, upper) \
(BigInt(lower) | (BigInt(upper - 2 * (upper & 0x80000000)) << BigInt(32)))
(BigInt(lower) | (BigInt(upper + 2 * (upper & 0x80000000)) << BigInt(32)))
#define LOAD_U64(addr, offset) \
UBIGINT_FROM_PAIR(DEREF_U32(addr, offset * 2), \