From 58a52ab5300d5312b8eea44096d7f5e1aca3d2e9 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 6 Dec 2022 09:53:45 -0800 Subject: [PATCH] Speed up running of JS compiler in LLD_REPORT_UNDEFINED mode. NFC (#18320) Avoid generating the full JS output, only generate the metadata. This saves about 10% of the cost. See: #16003 --- emcc.py | 25 ++++++++----------------- emscripten.py | 17 ++++++++++++----- src/compiler.js | 14 +++++++++++++- src/jsifier.js | 5 +++++ src/settings_internal.js | 5 ----- 5 files changed, 38 insertions(+), 28 deletions(-) diff --git a/emcc.py b/emcc.py index a65b95d74f2dc..60ea9c1f91762 100755 --- a/emcc.py +++ b/emcc.py @@ -508,23 +508,14 @@ def get_all_js_syms(): # TODO(sbc): Find a way to optimize this. Potentially we could add a super-set # mode of the js compiler that would generate a list of all possible symbols # that could be checked in. - old_full = settings.INCLUDE_FULL_LIBRARY - try: - # Temporarily define INCLUDE_FULL_LIBRARY since we want a full list - # of all available JS library functions. - settings.INCLUDE_FULL_LIBRARY = True - settings.ONLY_CALC_JS_SYMBOLS = True - emscripten.generate_struct_info() - glue, forwarded_data = emscripten.compile_settings() - forwarded_json = json.loads(forwarded_data) - library_syms = set() - for name in forwarded_json['librarySymbols']: - if shared.is_c_symbol(name): - name = shared.demangle_c_symbol_name(name) - library_syms.add(name) - finally: - settings.ONLY_CALC_JS_SYMBOLS = False - settings.INCLUDE_FULL_LIBRARY = old_full + emscripten.generate_struct_info() + glue, forwarded_data = emscripten.compile_javascript(symbols_only=True) + forwarded_json = json.loads(forwarded_data) + library_syms = set() + for name in forwarded_json: + if shared.is_c_symbol(name): + name = shared.demangle_c_symbol_name(name) + library_syms.add(name) return library_syms diff --git a/emscripten.py b/emscripten.py index 9e6a7c3bbfabd..37c5fbe6adde7 100644 --- a/emscripten.py +++ b/emscripten.py @@ -179,7 +179,7 @@ def apply_static_code_hooks(forwarded_json, code): return code -def compile_settings(): +def compile_javascript(symbols_only=False): stderr_file = os.environ.get('EMCC_STDERR_FILE') if stderr_file: stderr_file = os.path.abspath(stderr_file) @@ -199,11 +199,18 @@ def compile_settings(): # Call js compiler env = os.environ.copy() env['EMCC_BUILD_DIR'] = os.getcwd() + args = [settings_file] + if symbols_only: + args += ['--symbols-only'] out = shared.run_js_tool(path_from_root('src/compiler.js'), - [settings_file], stdout=subprocess.PIPE, stderr=stderr_file, + args, stdout=subprocess.PIPE, stderr=stderr_file, cwd=path_from_root('src'), env=env, encoding='utf-8') - assert '//FORWARDED_DATA:' in out, 'Did not receive forwarded data in pre output - process failed?' - glue, forwarded_data = out.split('//FORWARDED_DATA:') + if symbols_only: + glue = None + forwarded_data = out + else: + assert '//FORWARDED_DATA:' in out, 'Did not receive forwarded data in pre output - process failed?' + glue, forwarded_data = out.split('//FORWARDED_DATA:') return glue, forwarded_data @@ -367,7 +374,7 @@ def emscript(in_wasm, out_wasm, outfile_js, memfile): if invoke_funcs: settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$getWasmTableEntry'] - glue, forwarded_data = compile_settings() + glue, forwarded_data = compile_javascript() if DEBUG: logger.debug(' emscript: glue took %s seconds' % (time.time() - t)) t = time.time() diff --git a/src/compiler.js b/src/compiler.js index 01d68976564d0..2a4a4086bd425 100755 --- a/src/compiler.js +++ b/src/compiler.js @@ -43,8 +43,17 @@ function load(f) { // Basic utilities load('utility.js'); + +const argv = process.argv.slice(2); +const symbolsOnly = argv.indexOf('--symbols-only'); +if (symbolsOnly != -1) { + argv.splice(symbolsOnly, 1); +} + +global.ONLY_CALC_JS_SYMBOLS = symbolsOnly != -1; + // Load settings from JSON passed on the command line -const settingsFile = process.argv[2]; +const settingsFile = argv[0]; assert(settingsFile); const settings = JSON.parse(read(settingsFile)); @@ -55,6 +64,9 @@ WASM_EXPORTS = new Set(WASM_EXPORTS); SIDE_MODULE_EXPORTS = new Set(SIDE_MODULE_EXPORTS); INCOMING_MODULE_JS_API = new Set(INCOMING_MODULE_JS_API); WEAK_IMPORTS = new Set(WEAK_IMPORTS); +if (ONLY_CALC_JS_SYMBOLS) { + INCLUDE_FULL_LIBRARY = 1; +} // Side modules are pure wasm and have no JS assert(!SIDE_MODULE, 'JS compiler should not run on side modules'); diff --git a/src/jsifier.js b/src/jsifier.js index d6ff10067cf13..bfcc08685f308 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -540,5 +540,10 @@ function ${name}(${args}) { // Data functionStubs.forEach(functionStubHandler); + if (ONLY_CALC_JS_SYMBOLS) { + print(JSON.stringify(librarySymbols)); + return; + } + finalCombiner(); } diff --git a/src/settings_internal.js b/src/settings_internal.js index 6cc34db4c0e13..3a8036f5cecd1 100644 --- a/src/settings_internal.js +++ b/src/settings_internal.js @@ -189,11 +189,6 @@ var SEPARATE_DWARF = false; // New WebAssembly exception handling var WASM_EXCEPTIONS = false; -// Used internally when running the JS compiler simply to generate list of all -// JS symbols. This is used by LLD_REPORT_UNDEFINED to generate a list of all -// JS library symbols. -var ONLY_CALC_JS_SYMBOLS = false; - // Set to true if the program has a main function. By default this is // enabled, but if `--no-entry` is passed, or if `_main` is not part of // EXPORTED_FUNCTIONS then this gets set to 0.