From b70e49179185757f86d6487e42746b5fe530c39d Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Wed, 18 Jan 2023 16:09:11 -0800 Subject: [PATCH] make_export_wrappers: Limit module exports to EXPORTED_FUNCTIONS This is code size win in pretty much all cases since thee are always a few wasm exports that don't need to be set on the module object. --- ChangeLog.md | 5 ++ emscripten.py | 40 ++++++------ src/library_browser.js | 4 +- src/library_sdl.js | 20 +++--- .../optimizer/applyDCEGraphRemovals-output.js | 4 ++ test/optimizer/applyDCEGraphRemovals.js | 8 ++- test/optimizer/emitDCEGraph-output.js | 10 +++ test/optimizer/emitDCEGraph.js | 6 ++ .../metadce/test_metadce_cxx_ctors1.jssize | 2 +- .../metadce/test_metadce_cxx_ctors2.jssize | 2 +- .../metadce/test_metadce_cxx_except.jssize | 2 +- .../test_metadce_cxx_except_wasm.jssize | 2 +- .../metadce/test_metadce_cxx_mangle.jssize | 2 +- .../metadce/test_metadce_cxx_noexcept.jssize | 2 +- .../metadce/test_metadce_hello_O0.jssize | 2 +- .../metadce/test_metadce_hello_O1.jssize | 2 +- .../metadce/test_metadce_hello_O2.jssize | 2 +- .../metadce/test_metadce_hello_O3.jssize | 2 +- .../metadce/test_metadce_hello_Os.jssize | 2 +- .../metadce/test_metadce_hello_Oz.jssize | 2 +- .../test_metadce_hello_export_nothing.jssize | 2 +- .../test_metadce_libcxxabi_message_O3.jssize | 2 +- test/other/metadce/test_metadce_mem_O3.jssize | 2 +- .../metadce/test_metadce_mem_O3_grow.jssize | 2 +- .../metadce/test_metadce_minimal_O0.jssize | 2 +- .../metadce/test_metadce_minimal_O1.jssize | 2 +- .../metadce/test_metadce_minimal_O2.jssize | 2 +- .../metadce/test_metadce_minimal_O3.jssize | 2 +- .../metadce/test_metadce_minimal_Os.jssize | 2 +- .../metadce/test_metadce_minimal_Oz.jssize | 2 +- .../test_metadce_minimal_pthreads.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 +- test/test_browser.py | 2 +- tools/acorn-optimizer.js | 64 ++++++++++++++++++- 36 files changed, 154 insertions(+), 61 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 4af620225c20c..148927b988e37 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -20,6 +20,11 @@ See docs/process.md for more on how version tagging works. 3.1.31 (in development) ----------------------- +- Symbols that were previously exported from native code, but only for internal + reasons, are no longer exported on the `Module` object by default. For + example, previously if you were using `Module._malloc` but not explicitly + including `_malloc` in `EXPORTED_FUNCTIONS` if might have been exported anyway + due to internal using of `malloc` within the JS library code. (#18564) - The `STACK_SIZE`, `STACK_ALIGN`, `POINTER_SIZE`, and `ASSERTIONS` JavaScript globals were removed by default. In debug builds a clear error is shown if you try to use these. (#18503) diff --git a/emscripten.py b/emscripten.py index 9b1c169bcf3e7..acfbf7bd75c8d 100644 --- a/emscripten.py +++ b/emscripten.py @@ -315,6 +315,9 @@ def emscript(in_wasm, out_wasm, outfile_js, memfile): if settings.RELOCATABLE and settings.MEMORY64 == 2: metadata.imports += ['__memory_base32'] + if settings.ASYNCIFY: + metadata.exports += ['asyncify_start_unwind', 'asyncify_stop_unwind', 'asyncify_start_rewind', 'asyncify_stop_rewind'] + update_settings_glue(out_wasm, metadata) if not settings.WASM_BIGINT and metadata.emJsFuncs: @@ -391,9 +394,6 @@ def emscript(in_wasm, out_wasm, outfile_js, memfile): exports = metadata.exports - if settings.ASYNCIFY: - exports += ['asyncify_start_unwind', 'asyncify_stop_unwind', 'asyncify_start_rewind', 'asyncify_stop_rewind'] - report_missing_symbols(forwarded_json['librarySymbols']) if not outfile_js: @@ -696,6 +696,15 @@ def make_export_wrappers(exports, delay_assignment): if name == '__cpp_exception': continue mangled = asmjs_mangle(name) + wrapper = '/** @type {function(...*):?} */\nvar %s = ' % mangled + + # TODO(sbc): Can we avoid exporting the dynCall_ functions on the module. + if mangled in settings.EXPORTED_FUNCTIONS or name.startswith('dynCall_'): + exported = 'Module["%s"] = ' % mangled + else: + exported = '' + wrapper += exported + # The emscripten stack functions are called very early (by writeStackCookie) before # the runtime is initialized so we can't create these wrappers that check for # runtimeInitialized. @@ -705,29 +714,20 @@ def make_export_wrappers(exports, delay_assignment): # With assertions enabled we create a wrapper that are calls get routed through, for # the lifetime of the program. if delay_assignment: - wrappers.append('''\ -/** @type {function(...*):?} */ -var %(mangled)s = Module["%(mangled)s"] = createExportWrapper("%(name)s"); -''' % {'mangled': mangled, 'name': name}) + wrapper += 'createExportWrapper("%s");' % name else: - wrappers.append('''\ -/** @type {function(...*):?} */ -var %(mangled)s = Module["%(mangled)s"] = createExportWrapper("%(name)s", asm); -''' % {'mangled': mangled, 'name': name}) + wrapper += 'createExportWrapper("%s", asm);' % name elif delay_assignment: # With assertions disabled the wrapper will replace the global var and Module var on # first use. - wrappers.append('''\ -/** @type {function(...*):?} */ -var %(mangled)s = Module["%(mangled)s"] = function() { - return (%(mangled)s = Module["%(mangled)s"] = Module["asm"]["%(name)s"]).apply(null, arguments); + wrapper += '''function() { + return (%(mangled)s = %(exported)sModule["asm"]["%(name)s"]).apply(null, arguments); }; -''' % {'mangled': mangled, 'name': name}) +''' % {'mangled': mangled, 'name': name, 'exported': exported} else: - wrappers.append('''\ -/** @type {function(...*):?} */ -var %(mangled)s = Module["%(mangled)s"] = asm["%(name)s"] -''' % {'mangled': mangled, 'name': name}) + wrapper += 'asm["%s"]' % name + + wrappers.append(wrapper) return wrappers diff --git a/src/library_browser.js b/src/library_browser.js index c873762d14821..555277ab12c00 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -1379,11 +1379,11 @@ var LibraryBrowser = { return 0; }, - emscripten_get_preloaded_image_data_from_FILE__deps: ['emscripten_get_preloaded_image_data'], + emscripten_get_preloaded_image_data_from_FILE__deps: ['emscripten_get_preloaded_image_data', 'fileno'], emscripten_get_preloaded_image_data_from_FILE__proxy: 'sync', emscripten_get_preloaded_image_data_from_FILE__sig: 'iiii', emscripten_get_preloaded_image_data_from_FILE: function(file, w, h) { - var fd = Module['_fileno'](file); + var fd = _fileno(file); var stream = FS.getStream(fd); if (stream) { return _emscripten_get_preloaded_image_data(stream.path, w, h); diff --git a/src/library_sdl.js b/src/library_sdl.js index ec25b9de7e5be..d52e85e992c2a 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -2262,13 +2262,13 @@ var LibrarySDL = { } } var callStbImage = function(func, params) { - var x = Module['_malloc']({{{ getNativeTypeSize('i32') }}}); - var y = Module['_malloc']({{{ getNativeTypeSize('i32') }}}); - var comp = Module['_malloc']({{{ getNativeTypeSize('i32') }}}); + var x = _malloc({{{ getNativeTypeSize('i32') }}}); + var y = _malloc({{{ getNativeTypeSize('i32') }}}); + var comp = _malloc({{{ getNativeTypeSize('i32') }}}); addCleanup(function() { - Module['_free'](x); - Module['_free'](y); - Module['_free'](comp); + _free(x); + _free(y); + _free(comp); if (data) Module['_stbi_image_free'](data); }); var data = Module['_' + func].apply(null, params.concat([x, y, comp, 0])); @@ -2307,10 +2307,10 @@ var LibrarySDL = { if (raw === null) err('Trying to reuse preloaded image, but freePreloadedMediaOnUse is set!'); #if STB_IMAGE var lengthBytes = lengthBytesUTF8(filename)+1; - var name = Module['_malloc'](lengthBytes); + var name = _malloc(lengthBytes); stringToUTF8(filename, name, lengthBytes); addCleanup(function() { - Module['_free'](name); + _free(name); }); raw = callStbImage('stbi_load', [name]); if (!raw) return 0; @@ -2765,7 +2765,7 @@ var LibrarySDL = { return 1; }, - Mix_LoadWAV_RW__deps: ['$PATH_FS'], + Mix_LoadWAV_RW__deps: ['$PATH_FS', 'fileno'], Mix_LoadWAV_RW__proxy: 'sync', Mix_LoadWAV_RW__sig: 'iii', Mix_LoadWAV_RW__docs: '/** @param {number|boolean=} freesrc */', @@ -2778,7 +2778,7 @@ var LibrarySDL = { if (type === 2/*SDL_RWOPS_STDFILE*/) { var fp = {{{ makeGetValue('rwopsID + ' + 28 /*hidden.stdio.fp*/, '0', 'i32') }}}; - var fd = Module['_fileno'](fp); + var fd = _fileno(fp); var stream = FS.getStream(fd); if (stream) { rwops = { filename: stream.path }; diff --git a/test/optimizer/applyDCEGraphRemovals-output.js b/test/optimizer/applyDCEGraphRemovals-output.js index 1e9a39ab99c04..826ab259d02ad 100644 --- a/test/optimizer/applyDCEGraphRemovals-output.js +++ b/test/optimizer/applyDCEGraphRemovals-output.js @@ -13,6 +13,8 @@ var expD3 = Module["expD3"] = asm["expD3"]; var expD4; +var expD5; + var expI1 = Module["expI1"] = function() { return (expI1 = Module["expI1"] = Module["asm"]["expI1"]).apply(null, arguments); }; @@ -27,6 +29,8 @@ var expI3 = Module["expI3"] = function() { var expI4; +var expI5; + expD1; Module["expD2"]; diff --git a/test/optimizer/applyDCEGraphRemovals.js b/test/optimizer/applyDCEGraphRemovals.js index 1f3bafc9d7083..5d579071983c2 100644 --- a/test/optimizer/applyDCEGraphRemovals.js +++ b/test/optimizer/applyDCEGraphRemovals.js @@ -6,6 +6,8 @@ var expD1 = Module['expD1'] = asm['expD1']; var expD2 = Module['expD2'] = asm['expD2']; var expD3 = Module['expD3'] = asm['expD3']; var expD4 = Module['expD4'] = asm['expD4']; +// Like above, but not exported on the Module +var expD5 = asm['expD5']; // exports gotten indirectly (async compilation var expI1 = Module['expI1'] = (function() { @@ -20,6 +22,10 @@ var expI3 = Module['expI3'] = (function() { var expI4 = Module['expI4'] = (function() { return (expI4 = Module['expI4'] = Module['asm']['expI4']).apply(null, arguments); }); +// Like above, but not exported on the Module +var expI5 = (function() { + return (expI5 = Module['asm']['expI5']).apply(null, arguments); +}); // add uses for some of them, leave *4 as non-roots expD1; @@ -30,4 +36,4 @@ expI1; Module['expI2']; asm['expI3']; -// EXTRA_INFO: { "unused": ["emcc$import$number", "emcc$import$name", "emcc$import$func", "emcc$export$expD4", "emcc$export$expI4"] } +// EXTRA_INFO: { "unused": ["emcc$import$number", "emcc$import$name", "emcc$import$func", "emcc$export$expD4", "emcc$export$expD5", "emcc$export$expI4", "emcc$export$expI5"] } diff --git a/test/optimizer/emitDCEGraph-output.js b/test/optimizer/emitDCEGraph-output.js index f83b3c0ca2eb9..f8210ca84cf1e 100644 --- a/test/optimizer/emitDCEGraph-output.js +++ b/test/optimizer/emitDCEGraph-output.js @@ -100,6 +100,11 @@ "export": "expD4", "reaches": [] }, + { + "name": "emcc$export$expD5", + "export": "expD5", + "reaches": [] + }, { "name": "emcc$export$expI1", "export": "expI1", @@ -123,6 +128,11 @@ "export": "expI4", "reaches": [] }, + { + "name": "emcc$export$expI5", + "export": "expI5", + "reaches": [] + }, { "name": "emcc$import$rootedFunc1", "import": [ diff --git a/test/optimizer/emitDCEGraph.js b/test/optimizer/emitDCEGraph.js index b29f993f84d3b..2814eea3db21c 100644 --- a/test/optimizer/emitDCEGraph.js +++ b/test/optimizer/emitDCEGraph.js @@ -49,6 +49,8 @@ var expD1 = Module['expD1'] = asm['expD1']; var expD2 = Module['expD2'] = asm['expD2']; var expD3 = Module['expD3'] = asm['expD3']; var expD4 = Module['expD4'] = asm['expD4']; +// Same as above but not export on the Module +var expD5 = asm['expD5']; // exports gotten indirectly (async compilation var expI1 = Module['expI1'] = function() { @@ -63,6 +65,10 @@ var expI3 = Module['expI3'] = function() { var expI4 = Module['expI4'] = function() { return (expI4 = Module['expI4'] = Module['asm']['expI4']).apply(null, arguments); }; +// Same as above but not export on the Module. +var expI5 = function() { + return (expI5 = Module['asm']['expI5']).apply(null, arguments); +}; // add uses for some of them expD1; diff --git a/test/other/metadce/test_metadce_cxx_ctors1.jssize b/test/other/metadce/test_metadce_cxx_ctors1.jssize index a50392120d850..d4c63614355b5 100644 --- a/test/other/metadce/test_metadce_cxx_ctors1.jssize +++ b/test/other/metadce/test_metadce_cxx_ctors1.jssize @@ -1 +1 @@ -26600 +26008 diff --git a/test/other/metadce/test_metadce_cxx_ctors2.jssize b/test/other/metadce/test_metadce_cxx_ctors2.jssize index 8e0e7bd87f081..af118f35f4f1f 100644 --- a/test/other/metadce/test_metadce_cxx_ctors2.jssize +++ b/test/other/metadce/test_metadce_cxx_ctors2.jssize @@ -1 +1 @@ -26564 +25972 diff --git a/test/other/metadce/test_metadce_cxx_except.jssize b/test/other/metadce/test_metadce_cxx_except.jssize index 33fce0b977e01..fc41fdfd7d3e3 100644 --- a/test/other/metadce/test_metadce_cxx_except.jssize +++ b/test/other/metadce/test_metadce_cxx_except.jssize @@ -1 +1 @@ -31193 +30545 diff --git a/test/other/metadce/test_metadce_cxx_except_wasm.jssize b/test/other/metadce/test_metadce_cxx_except_wasm.jssize index b5eebea88b7df..76de69f3c902a 100644 --- a/test/other/metadce/test_metadce_cxx_except_wasm.jssize +++ b/test/other/metadce/test_metadce_cxx_except_wasm.jssize @@ -1 +1 @@ -26078 +25581 diff --git a/test/other/metadce/test_metadce_cxx_mangle.jssize b/test/other/metadce/test_metadce_cxx_mangle.jssize index 765e502ea7d94..fc41fdfd7d3e3 100644 --- a/test/other/metadce/test_metadce_cxx_mangle.jssize +++ b/test/other/metadce/test_metadce_cxx_mangle.jssize @@ -1 +1 @@ -31437 +30545 diff --git a/test/other/metadce/test_metadce_cxx_noexcept.jssize b/test/other/metadce/test_metadce_cxx_noexcept.jssize index a50392120d850..d4c63614355b5 100644 --- a/test/other/metadce/test_metadce_cxx_noexcept.jssize +++ b/test/other/metadce/test_metadce_cxx_noexcept.jssize @@ -1 +1 @@ -26600 +26008 diff --git a/test/other/metadce/test_metadce_hello_O0.jssize b/test/other/metadce/test_metadce_hello_O0.jssize index 3bbd88ce3d9ec..ec13b87ae6813 100644 --- a/test/other/metadce/test_metadce_hello_O0.jssize +++ b/test/other/metadce/test_metadce_hello_O0.jssize @@ -1 +1 @@ -26963 +26284 diff --git a/test/other/metadce/test_metadce_hello_O1.jssize b/test/other/metadce/test_metadce_hello_O1.jssize index 30b0b1238a738..9348bfb48da92 100644 --- a/test/other/metadce/test_metadce_hello_O1.jssize +++ b/test/other/metadce/test_metadce_hello_O1.jssize @@ -1 +1 @@ -9214 +8678 diff --git a/test/other/metadce/test_metadce_hello_O2.jssize b/test/other/metadce/test_metadce_hello_O2.jssize index aaf5e677e49c9..897b8ab2cd30b 100644 --- a/test/other/metadce/test_metadce_hello_O2.jssize +++ b/test/other/metadce/test_metadce_hello_O2.jssize @@ -1 +1 @@ -6610 +6138 diff --git a/test/other/metadce/test_metadce_hello_O3.jssize b/test/other/metadce/test_metadce_hello_O3.jssize index 8cf9e4322d772..9e94392fd81fb 100644 --- a/test/other/metadce/test_metadce_hello_O3.jssize +++ b/test/other/metadce/test_metadce_hello_O3.jssize @@ -1 +1 @@ -6060 +5968 diff --git a/test/other/metadce/test_metadce_hello_Os.jssize b/test/other/metadce/test_metadce_hello_Os.jssize index 8cf9e4322d772..9e94392fd81fb 100644 --- a/test/other/metadce/test_metadce_hello_Os.jssize +++ b/test/other/metadce/test_metadce_hello_Os.jssize @@ -1 +1 @@ -6060 +5968 diff --git a/test/other/metadce/test_metadce_hello_Oz.jssize b/test/other/metadce/test_metadce_hello_Oz.jssize index a92ae411aa57e..297504bace432 100644 --- a/test/other/metadce/test_metadce_hello_Oz.jssize +++ b/test/other/metadce/test_metadce_hello_Oz.jssize @@ -1 +1 @@ -6019 +5927 diff --git a/test/other/metadce/test_metadce_hello_export_nothing.jssize b/test/other/metadce/test_metadce_hello_export_nothing.jssize index 383fa505c5afe..31e10e4977058 100644 --- a/test/other/metadce/test_metadce_hello_export_nothing.jssize +++ b/test/other/metadce/test_metadce_hello_export_nothing.jssize @@ -1 +1 @@ -4740 +4648 diff --git a/test/other/metadce/test_metadce_libcxxabi_message_O3.jssize b/test/other/metadce/test_metadce_libcxxabi_message_O3.jssize index 66ff790e932f6..e9ebc91cca26e 100644 --- a/test/other/metadce/test_metadce_libcxxabi_message_O3.jssize +++ b/test/other/metadce/test_metadce_libcxxabi_message_O3.jssize @@ -1 +1 @@ -5333 +5241 diff --git a/test/other/metadce/test_metadce_mem_O3.jssize b/test/other/metadce/test_metadce_mem_O3.jssize index e36377c6be456..3dec175604739 100644 --- a/test/other/metadce/test_metadce_mem_O3.jssize +++ b/test/other/metadce/test_metadce_mem_O3.jssize @@ -1 +1 @@ -6213 +6094 diff --git a/test/other/metadce/test_metadce_mem_O3_grow.jssize b/test/other/metadce/test_metadce_mem_O3_grow.jssize index 72298135d0b70..725a719f3bcb1 100644 --- a/test/other/metadce/test_metadce_mem_O3_grow.jssize +++ b/test/other/metadce/test_metadce_mem_O3_grow.jssize @@ -1 +1 @@ -6555 +6436 diff --git a/test/other/metadce/test_metadce_minimal_O0.jssize b/test/other/metadce/test_metadce_minimal_O0.jssize index c670bebed580e..b4cf60a2b7348 100644 --- a/test/other/metadce/test_metadce_minimal_O0.jssize +++ b/test/other/metadce/test_metadce_minimal_O0.jssize @@ -1 +1 @@ -23612 +22850 diff --git a/test/other/metadce/test_metadce_minimal_O1.jssize b/test/other/metadce/test_metadce_minimal_O1.jssize index f98cf06b14d6e..1c95e4aa7ca94 100644 --- a/test/other/metadce/test_metadce_minimal_O1.jssize +++ b/test/other/metadce/test_metadce_minimal_O1.jssize @@ -1 +1 @@ -5732 +5196 diff --git a/test/other/metadce/test_metadce_minimal_O2.jssize b/test/other/metadce/test_metadce_minimal_O2.jssize index 17151eb01cac0..7e3ca6598e673 100644 --- a/test/other/metadce/test_metadce_minimal_O2.jssize +++ b/test/other/metadce/test_metadce_minimal_O2.jssize @@ -1 +1 @@ -4447 +3975 diff --git a/test/other/metadce/test_metadce_minimal_O3.jssize b/test/other/metadce/test_metadce_minimal_O3.jssize index 2d2c4aa94bfd9..fb97fa2917c97 100644 --- a/test/other/metadce/test_metadce_minimal_O3.jssize +++ b/test/other/metadce/test_metadce_minimal_O3.jssize @@ -1 +1 @@ -3956 +3864 diff --git a/test/other/metadce/test_metadce_minimal_Os.jssize b/test/other/metadce/test_metadce_minimal_Os.jssize index 2d2c4aa94bfd9..fb97fa2917c97 100644 --- a/test/other/metadce/test_metadce_minimal_Os.jssize +++ b/test/other/metadce/test_metadce_minimal_Os.jssize @@ -1 +1 @@ -3956 +3864 diff --git a/test/other/metadce/test_metadce_minimal_Oz.jssize b/test/other/metadce/test_metadce_minimal_Oz.jssize index 2d2c4aa94bfd9..fb97fa2917c97 100644 --- a/test/other/metadce/test_metadce_minimal_Oz.jssize +++ b/test/other/metadce/test_metadce_minimal_Oz.jssize @@ -1 +1 @@ -3956 +3864 diff --git a/test/other/metadce/test_metadce_minimal_pthreads.jssize b/test/other/metadce/test_metadce_minimal_pthreads.jssize index 3b4b7969225f6..de8cd474efcc4 100644 --- a/test/other/metadce/test_metadce_minimal_pthreads.jssize +++ b/test/other/metadce/test_metadce_minimal_pthreads.jssize @@ -1 +1 @@ -16177 +15787 diff --git a/test/other/test_unoptimized_code_size.js.size b/test/other/test_unoptimized_code_size.js.size index 020276d52cb4a..721b89b3d3279 100644 --- a/test/other/test_unoptimized_code_size.js.size +++ b/test/other/test_unoptimized_code_size.js.size @@ -1 +1 @@ -67096 +66571 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 c5baeb63e72d8..175dcbbbcb303 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 @@ -38780 +38518 diff --git a/test/other/test_unoptimized_code_size_strict.js.size b/test/other/test_unoptimized_code_size_strict.js.size index 3751d9c28be29..073cc889724f6 100644 --- a/test/other/test_unoptimized_code_size_strict.js.size +++ b/test/other/test_unoptimized_code_size_strict.js.size @@ -1 +1 @@ -65962 +65437 diff --git a/test/test_browser.py b/test/test_browser.py index 41bbfdc125322..296e8ca106e4d 100644 --- a/test/test_browser.py +++ b/test/test_browser.py @@ -4392,7 +4392,7 @@ def test_small_js_flags(self): size = os.path.getsize('test.js') print('size:', size) # Note that this size includes test harness additions (for reporting the result, etc.). - self.assertLess(abs(size - 5169), 100) + self.assertLess(abs(size - 5059), 100) # Tests that it is possible to initialize and render WebGL content in a pthread by using OffscreenCanvas. # -DTEST_CHAINED_WEBGL_CONTEXT_PASSING: Tests that it is possible to transfer WebGL canvas in a chain from main thread -> thread 1 -> thread 2 and then init and render WebGL content there. diff --git a/tools/acorn-optimizer.js b/tools/acorn-optimizer.js index d0d2c709e23ad..386ed79d3703f 100755 --- a/tools/acorn-optimizer.js +++ b/tools/acorn-optimizer.js @@ -584,6 +584,28 @@ function isDynamicDynCall(node) { ); } +function isExportWrapperFunction(f) { + let found; + fullWalk(f.body, inner => { + if (inner.type == 'ReturnStatement') { + const rtn = inner.argument; + if (rtn.type == 'CallExpression') { + let target = rtn.callee.object; + if (target.type == 'ParenthesizedExpression') { + target = target.expression; + } + if (target.type == 'AssignmentExpression') { + const rhs = target.right; + if (isAsmUse(rhs)) { + found = getAsmOrModuleUseName(rhs); + } + } + } + } + }); + return found; +} + // // Emit the DCE graph, to help optimize the combined JS+wasm. // This finds where JS depends on wasm, and where wasm depends @@ -640,6 +662,10 @@ function emitDCEGraph(ast) { // // or // + // var _malloc = asm["_malloc"]; + // + // or + // // var _malloc = Module["_malloc"] = (function() { // return Module["asm"]["_malloc"].apply(null, arguments); // }); @@ -698,7 +724,21 @@ function emitDCEGraph(ast) { const item = node.declarations[0]; const name = item.id.name; const value = item.init; - if (value && value.type === 'AssignmentExpression') { + if (value && isAsmUse(value)) { + const asmName = getAsmOrModuleUseName(value); + // this is + // var _x = asm['x']; + saveAsmExport(name, asmName); + emptyOut(node); + } else if (value && value.type === 'FunctionExpression') { + // this is + // var x = function() { return (x = Module['asm']['x']).apply .. } + let asmName = isExportWrapperFunction(value); + if (asmName) { + saveAsmExport(name, asmName); + emptyOut(node); + } + } else if (value && value.type === 'AssignmentExpression') { const assigned = value.left; if (isModuleUse(assigned) && getAsmOrModuleUseName(assigned) === name) { // this is @@ -942,6 +982,7 @@ function applyDCEGraphRemovals(ast) { }); } else if (node.type === 'AssignmentExpression') { // when we assign to a thing we don't need, we can just remove the assign + // var x = Module['x'] = asm['x']; const target = node.left; if (isAsmUse(target) || isModuleUse(target)) { const name = getAsmOrModuleUseName(target); @@ -952,6 +993,27 @@ function applyDCEGraphRemovals(ast) { convertToNothingInVarInit(node); } } + } else if (node.type === 'VariableDeclaration') { + // Handle the case we declare variable but don't assign the module: + // var x = asm['x']; + // and + // var x = function() { return (x = asm['x']).apply(...) }; + const init = node.declarations[0].init; + if (init) { + if (isAsmUse(init)) { + const name = getAsmOrModuleUseName(init); + const full = 'emcc$export$' + name; + if (unused.has(full)) { + convertToNothingInVarInit(init); + } + } else if (init.type == 'FunctionExpression') { + const name = isExportWrapperFunction(init); + const full = 'emcc$export$' + name; + if (unused.has(full)) { + convertToNothingInVarInit(init); + } + } + } } else if (node.type === 'ExpressionStatement') { const expr = node.expression; // In the minimal runtime code pattern we have just