From 40252f574b8f99a557c06d5733a8c69292275def Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 27 Feb 2024 13:33:12 -0800 Subject: [PATCH] Allow HEAPX symbols in EXPORT_RUNTIME_METHODS (#21439) - Factor out updateMemoryViews. - Enable HEAPXX exports to be specified in EXPORT_RUNTIME_METHODS. - Add all HEAP symbosl to EXPORT_RUNTIME_METHODS unless in STRICT mode. Replaces #21407 --- ChangeLog.md | 4 ++ src/modules.js | 11 +++++ src/preamble.js | 19 +------- src/preamble_minimal.js | 37 ++------------ src/runtime_shared.js | 48 +++++++++++++++++++ .../metadce/test_metadce_minimal_64.gzsize | 2 +- .../metadce/test_metadce_minimal_64.jssize | 2 +- .../metadce/test_metadce_minimal_O0.gzsize | 2 +- .../metadce/test_metadce_minimal_O0.jssize | 2 +- .../metadce/test_metadce_minimal_O1.gzsize | 2 +- .../metadce/test_metadce_minimal_O1.jssize | 2 +- .../metadce/test_metadce_minimal_O2.gzsize | 2 +- .../metadce/test_metadce_minimal_O2.jssize | 2 +- .../metadce/test_metadce_minimal_O3.gzsize | 2 +- .../metadce/test_metadce_minimal_O3.jssize | 2 +- .../metadce/test_metadce_minimal_Os.gzsize | 2 +- .../metadce/test_metadce_minimal_Os.jssize | 2 +- .../test_metadce_minimal_Oz-ctors.gzsize | 2 +- .../test_metadce_minimal_Oz-ctors.jssize | 2 +- .../metadce/test_metadce_minimal_Oz.gzsize | 2 +- .../metadce/test_metadce_minimal_Oz.jssize | 2 +- .../test_metadce_minimal_wasmfs.gzsize | 2 +- .../test_metadce_minimal_wasmfs.jssize | 2 +- test/other/test_unoptimized_code_size.js.size | 2 +- ...t_unoptimized_code_size_no_asserts.js.size | 2 +- .../test_unoptimized_code_size_strict.js.size | 2 +- tools/link.py | 12 +++++ 27 files changed, 102 insertions(+), 71 deletions(-) create mode 100644 src/runtime_shared.js diff --git a/ChangeLog.md b/ChangeLog.md index b0b22bd35b8c..21b9e4df01ed 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -21,6 +21,10 @@ See docs/process.md for more on how version tagging works. 3.1.55 (in development) ----------------------- - Update sdl2-mixer port from 2.6.0 to 2.8.0 +- In `STRICT` mode the `HEAPXX` symbols (such as `HEAP8` and `HEAP32`) are now + only exported on demand. This means that they must be added to + `EXPORTED_RUNTIME_METHODS` for them to appear on the `Module` object. For + now, this only effects users of `STRICT` mode. (#21439) 3.1.54 - 02/15/24 ----------------- diff --git a/src/modules.js b/src/modules.js index 85d58a992c8e..20202bd0e42c 100644 --- a/src/modules.js +++ b/src/modules.js @@ -349,6 +349,10 @@ function exportRuntime() { // being exported. how we show the message depends on whether it's // a function (almost all of them) or a number. function maybeExport(name) { + // HEAP objects are exported separately in updateMemoryViews + if (name.startsWith('HEAP')) { + return; + } // if requested to be exported, export it if (EXPORTED_RUNTIME_METHODS_SET.has(name)) { let exported = name; @@ -385,6 +389,13 @@ function exportRuntime() { 'abort', 'wasmMemory', 'wasmExports', + 'HEAPF32', + 'HEAPF64', + 'HEAP_DATA_VIEW', + 'HEAP8', 'HEAPU8', + 'HEAP16', 'HEAPU16', + 'HEAP32', 'HEAPU32', + 'HEAP64', 'HEAPU64', ]; // These are actually native wasm functions these days but we allow exporting diff --git a/src/preamble.js b/src/preamble.js index 7526ae4d587f..b53ad03f69dc 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -138,24 +138,7 @@ var HEAP, var HEAP_DATA_VIEW; #endif -function updateMemoryViews() { - var b = wasmMemory.buffer; -#if SUPPORT_BIG_ENDIAN - Module['HEAP_DATA_VIEW'] = HEAP_DATA_VIEW = new DataView(b); -#endif - Module['HEAP8'] = HEAP8 = new Int8Array(b); - Module['HEAP16'] = HEAP16 = new Int16Array(b); - Module['HEAPU8'] = HEAPU8 = new Uint8Array(b); - Module['HEAPU16'] = HEAPU16 = new Uint16Array(b); - Module['HEAP32'] = HEAP32 = new Int32Array(b); - Module['HEAPU32'] = HEAPU32 = new Uint32Array(b); - Module['HEAPF32'] = HEAPF32 = new Float32Array(b); - Module['HEAPF64'] = HEAPF64 = new Float64Array(b); -#if WASM_BIGINT - Module['HEAP64'] = HEAP64 = new BigInt64Array(b); - Module['HEAPU64'] = HEAPU64 = new BigUint64Array(b); -#endif -} +#include "runtime_shared.js" #if ASSERTIONS assert(!Module['STACK_SIZE'], 'STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time') diff --git a/src/preamble_minimal.js b/src/preamble_minimal.js index ae7004556321..82471a4a940c 100644 --- a/src/preamble_minimal.js +++ b/src/preamble_minimal.js @@ -4,17 +4,6 @@ * SPDX-License-Identifier: MIT */ -{{{ - // Helper function to export a symbol on the module object - // if requested. - globalThis.maybeExport = (x) => MODULARIZE && EXPORT_ALL ? `Module['${x}'] = ` : ''; - // Export to the AudioWorkletGlobalScope the needed variables to access - // the heap. AudioWorkletGlobalScope is unable to access global JS vars - // in the compiled main JS file. - globalThis.maybeExportIfAudioWorklet = (x) => (MODULARIZE && EXPORT_ALL) || AUDIO_WORKLET ? `Module['${x}'] = ` : ''; - null; -}}} - #if SAFE_HEAP #include "runtime_safe_heap.js" #endif @@ -65,27 +54,7 @@ var HEAP8, HEAP16, HEAP32, HEAPU8, HEAPU16, HEAPU32, HEAPF32, HEAPF64, #endif wasmMemory; -function updateMemoryViews() { - var b = wasmMemory.buffer; -#if ASSERTIONS && SHARED_MEMORY - assert(b instanceof SharedArrayBuffer, 'requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag'); -#endif -#if SUPPORT_BIG_ENDIAN - {{{ maybeExport('HEAP_DATA_VIEW') }}} HEAP_DATA_VIEW = new DataView(b); -#endif - {{{ maybeExport('HEAP8') }}} HEAP8 = new Int8Array(b); - {{{ maybeExport('HEAP16') }}} HEAP16 = new Int16Array(b); - {{{ maybeExport('HEAPU8') }}} HEAPU8 = new Uint8Array(b); - {{{ maybeExport('HEAPU16') }}} HEAPU16 = new Uint16Array(b); - {{{ maybeExport('HEAP32') }}} HEAP32 = new Int32Array(b); - {{{ maybeExportIfAudioWorklet('HEAPU32') }}} HEAPU32 = new Uint32Array(b); - {{{ maybeExportIfAudioWorklet('HEAPF32') }}} HEAPF32 = new Float32Array(b); - {{{ maybeExport('HEAPF64') }}} HEAPF64 = new Float64Array(b); -#if WASM_BIGINT - {{{ maybeExport('HEAP64') }}} HEAP64 = new BigInt64Array(b); - {{{ maybeExport('HEAPU64') }}} HEAPU64 = new BigUint64Array(b); -#endif -} +#include "runtime_shared.js" #if IMPORTED_MEMORY #if PTHREADS @@ -116,6 +85,10 @@ else { #endif // MODULARIZE #endif // PTHREADS +#if ASSERTIONS && SHARED_MEMORY +assert(wasmMemory.buffer instanceof SharedArrayBuffer, 'requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag'); +#endif + updateMemoryViews(); #endif // IMPORTED_MEMORY diff --git a/src/runtime_shared.js b/src/runtime_shared.js new file mode 100644 index 000000000000..0cf12cd87488 --- /dev/null +++ b/src/runtime_shared.js @@ -0,0 +1,48 @@ +/** + * @license + * Copyright 2024 The Emscripten Authors + * SPDX-License-Identifier: MIT + */ + +{{{ + // Helper function to export a heap symbol on the module object, + // if requested. + globalThis.maybeExportHeap = (x) => { + // For now, we export all heap object when not building with MINIMAL_RUNTIME + let shouldExport = !MINIMAL_RUNTIME && !STRICT; + if (!shouldExport) { + if (MODULARIZE && EXPORT_ALL) { + shouldExport = true; + } else if (AUDIO_WORKLET && (x == 'HEAP32' || x == 'HEAPU32')) { + // Export to the AudioWorkletGlobalScope the needed variables to access + // the heap. AudioWorkletGlobalScope is unable to access global JS vars + // in the compiled main JS file. + shouldExport = true; + } else if (EXPORTED_RUNTIME_METHODS.includes(x)) { + shouldExport = true; + } + } + + return shouldExport ? `Module['${x}'] = ` : ''; + }; + null; +}}} + +function updateMemoryViews() { + var b = wasmMemory.buffer; +#if SUPPORT_BIG_ENDIAN + {{{ maybeExport('HEAP_DATA_VIEW') }}} HEAP_DATA_VIEW = new DataView(b); +#endif + {{{ maybeExportHeap('HEAP8') }}}HEAP8 = new Int8Array(b); + {{{ maybeExportHeap('HEAP16') }}}HEAP16 = new Int16Array(b); + {{{ maybeExportHeap('HEAPU8') }}}HEAPU8 = new Uint8Array(b); + {{{ maybeExportHeap('HEAPU16') }}}HEAPU16 = new Uint16Array(b); + {{{ maybeExportHeap('HEAP32') }}}HEAP32 = new Int32Array(b); + {{{ maybeExportHeap('HEAPU32') }}}HEAPU32 = new Uint32Array(b); + {{{ maybeExportHeap('HEAPF32') }}}HEAPF32 = new Float32Array(b); + {{{ maybeExportHeap('HEAPF64') }}}HEAPF64 = new Float64Array(b); +#if WASM_BIGINT + {{{ maybeExportHeap('HEAP64') }}}HEAP64 = new BigInt64Array(b); + {{{ maybeExportHeap('HEAPU64') }}}HEAPU64 = new BigUint64Array(b); +#endif +} diff --git a/test/other/metadce/test_metadce_minimal_64.gzsize b/test/other/metadce/test_metadce_minimal_64.gzsize index 1c38c9071a6a..e41cd7af5901 100644 --- a/test/other/metadce/test_metadce_minimal_64.gzsize +++ b/test/other/metadce/test_metadce_minimal_64.gzsize @@ -1 +1 @@ -1725 +1685 diff --git a/test/other/metadce/test_metadce_minimal_64.jssize b/test/other/metadce/test_metadce_minimal_64.jssize index a47988fa3ccb..c9818c5c65df 100644 --- a/test/other/metadce/test_metadce_minimal_64.jssize +++ b/test/other/metadce/test_metadce_minimal_64.jssize @@ -1 +1 @@ -3635 +3541 diff --git a/test/other/metadce/test_metadce_minimal_O0.gzsize b/test/other/metadce/test_metadce_minimal_O0.gzsize index d6d90eab770c..93ab05de17c2 100644 --- a/test/other/metadce/test_metadce_minimal_O0.gzsize +++ b/test/other/metadce/test_metadce_minimal_O0.gzsize @@ -1 +1 @@ -6845 +6858 diff --git a/test/other/metadce/test_metadce_minimal_O0.jssize b/test/other/metadce/test_metadce_minimal_O0.jssize index 27a84977b341..4a53ea86c7ff 100644 --- a/test/other/metadce/test_metadce_minimal_O0.jssize +++ b/test/other/metadce/test_metadce_minimal_O0.jssize @@ -1 +1 @@ -18753 +18751 diff --git a/test/other/metadce/test_metadce_minimal_O1.gzsize b/test/other/metadce/test_metadce_minimal_O1.gzsize index 5bcfdd68e8ca..b4c6992e70a8 100644 --- a/test/other/metadce/test_metadce_minimal_O1.gzsize +++ b/test/other/metadce/test_metadce_minimal_O1.gzsize @@ -1 +1 @@ -1827 +1796 diff --git a/test/other/metadce/test_metadce_minimal_O1.jssize b/test/other/metadce/test_metadce_minimal_O1.jssize index ec44c91a80e8..fbb5de3eafa1 100644 --- a/test/other/metadce/test_metadce_minimal_O1.jssize +++ b/test/other/metadce/test_metadce_minimal_O1.jssize @@ -1 +1 @@ -4419 +4328 diff --git a/test/other/metadce/test_metadce_minimal_O2.gzsize b/test/other/metadce/test_metadce_minimal_O2.gzsize index d1b8e2f29a87..0e1b3bc63656 100644 --- a/test/other/metadce/test_metadce_minimal_O2.gzsize +++ b/test/other/metadce/test_metadce_minimal_O2.gzsize @@ -1 +1 @@ -1660 +1627 diff --git a/test/other/metadce/test_metadce_minimal_O2.jssize b/test/other/metadce/test_metadce_minimal_O2.jssize index 0f1c48c0179c..c0fac8d63000 100644 --- a/test/other/metadce/test_metadce_minimal_O2.jssize +++ b/test/other/metadce/test_metadce_minimal_O2.jssize @@ -1 +1 @@ -3362 +3287 diff --git a/test/other/metadce/test_metadce_minimal_O3.gzsize b/test/other/metadce/test_metadce_minimal_O3.gzsize index 871215b3e56b..4b24aeddf584 100644 --- a/test/other/metadce/test_metadce_minimal_O3.gzsize +++ b/test/other/metadce/test_metadce_minimal_O3.gzsize @@ -1 +1 @@ -1618 +1591 diff --git a/test/other/metadce/test_metadce_minimal_O3.jssize b/test/other/metadce/test_metadce_minimal_O3.jssize index 1d439c4d85b4..c23f53c20b3d 100644 --- a/test/other/metadce/test_metadce_minimal_O3.jssize +++ b/test/other/metadce/test_metadce_minimal_O3.jssize @@ -1 +1 @@ -3312 +3237 diff --git a/test/other/metadce/test_metadce_minimal_Os.gzsize b/test/other/metadce/test_metadce_minimal_Os.gzsize index 871215b3e56b..4b24aeddf584 100644 --- a/test/other/metadce/test_metadce_minimal_Os.gzsize +++ b/test/other/metadce/test_metadce_minimal_Os.gzsize @@ -1 +1 @@ -1618 +1591 diff --git a/test/other/metadce/test_metadce_minimal_Os.jssize b/test/other/metadce/test_metadce_minimal_Os.jssize index 1d439c4d85b4..c23f53c20b3d 100644 --- a/test/other/metadce/test_metadce_minimal_Os.jssize +++ b/test/other/metadce/test_metadce_minimal_Os.jssize @@ -1 +1 @@ -3312 +3237 diff --git a/test/other/metadce/test_metadce_minimal_Oz-ctors.gzsize b/test/other/metadce/test_metadce_minimal_Oz-ctors.gzsize index 480d250f51e2..2907ff583360 100644 --- a/test/other/metadce/test_metadce_minimal_Oz-ctors.gzsize +++ b/test/other/metadce/test_metadce_minimal_Oz-ctors.gzsize @@ -1 +1 @@ -1610 +1583 diff --git a/test/other/metadce/test_metadce_minimal_Oz-ctors.jssize b/test/other/metadce/test_metadce_minimal_Oz-ctors.jssize index d7a33ea4704b..28206c288175 100644 --- a/test/other/metadce/test_metadce_minimal_Oz-ctors.jssize +++ b/test/other/metadce/test_metadce_minimal_Oz-ctors.jssize @@ -1 +1 @@ -3297 +3222 diff --git a/test/other/metadce/test_metadce_minimal_Oz.gzsize b/test/other/metadce/test_metadce_minimal_Oz.gzsize index 871215b3e56b..4b24aeddf584 100644 --- a/test/other/metadce/test_metadce_minimal_Oz.gzsize +++ b/test/other/metadce/test_metadce_minimal_Oz.gzsize @@ -1 +1 @@ -1618 +1591 diff --git a/test/other/metadce/test_metadce_minimal_Oz.jssize b/test/other/metadce/test_metadce_minimal_Oz.jssize index 1d439c4d85b4..c23f53c20b3d 100644 --- a/test/other/metadce/test_metadce_minimal_Oz.jssize +++ b/test/other/metadce/test_metadce_minimal_Oz.jssize @@ -1 +1 @@ -3312 +3237 diff --git a/test/other/metadce/test_metadce_minimal_wasmfs.gzsize b/test/other/metadce/test_metadce_minimal_wasmfs.gzsize index 871215b3e56b..4b24aeddf584 100644 --- a/test/other/metadce/test_metadce_minimal_wasmfs.gzsize +++ b/test/other/metadce/test_metadce_minimal_wasmfs.gzsize @@ -1 +1 @@ -1618 +1591 diff --git a/test/other/metadce/test_metadce_minimal_wasmfs.jssize b/test/other/metadce/test_metadce_minimal_wasmfs.jssize index 1d439c4d85b4..c23f53c20b3d 100644 --- a/test/other/metadce/test_metadce_minimal_wasmfs.jssize +++ b/test/other/metadce/test_metadce_minimal_wasmfs.jssize @@ -1 +1 @@ -3312 +3237 diff --git a/test/other/test_unoptimized_code_size.js.size b/test/other/test_unoptimized_code_size.js.size index 545b21525a14..08e9897ea671 100644 --- a/test/other/test_unoptimized_code_size.js.size +++ b/test/other/test_unoptimized_code_size.js.size @@ -1 +1 @@ -58034 +58097 diff --git a/test/other/test_unoptimized_code_size_no_asserts.js.size b/test/other/test_unoptimized_code_size_no_asserts.js.size index 996164ae6936..9874731bce55 100644 --- a/test/other/test_unoptimized_code_size_no_asserts.js.size +++ b/test/other/test_unoptimized_code_size_no_asserts.js.size @@ -1 +1 @@ -31565 +31628 diff --git a/test/other/test_unoptimized_code_size_strict.js.size b/test/other/test_unoptimized_code_size_strict.js.size index bdb09b0d6def..920f0bb214c8 100644 --- a/test/other/test_unoptimized_code_size_strict.js.size +++ b/test/other/test_unoptimized_code_size_strict.js.size @@ -1 +1 @@ -56997 +57049 diff --git a/tools/link.py b/tools/link.py index 969af7942a72..f2f631dd5213 100644 --- a/tools/link.py +++ b/tools/link.py @@ -880,6 +880,18 @@ def phase_linker_setup(options, state, newargs): else: default_setting('INCOMING_MODULE_JS_API', []) + if not settings.MINIMAL_RUNTIME and not settings.STRICT: + # Export the HEAP object by default, when not running in STRICT mode + settings.EXPORTED_RUNTIME_METHODS.extend([ + 'HEAPF32', + 'HEAPF64', + 'HEAP_DATA_VIEW', + 'HEAP8', 'HEAPU8', + 'HEAP16', 'HEAPU16', + 'HEAP32', 'HEAPU32', + 'HEAP64', 'HEAPU64', + ]) + # Default to TEXTDECODER=2 (always use TextDecoder to decode UTF-8 strings) # in -Oz builds, since custom decoder for UTF-8 takes up space. # In pthreads enabled builds, TEXTDECODER==2 may not work, see