Skip to content

Commit

Permalink
Avoid creating wrapper thunks or wasm exports
Browse files Browse the repository at this point in the history
In debug builds nothing really changes here since we exported functions
still get statically assigned to debug wrappers/thunks.

However, after this change, in release builds, if you attempt to access
`_foo` (internally) or `Module['_foo']` externally before the module
is loaded you will now get `undefined`.

Since it was always the case that calling these function would crash
anyway, the only effected folks would be folks that take the reference
early and then call later. e.g.

```
var myfunc = Module['_foo'];  // Run before module is loaded
// wait until loaded
myfunc();  // This will no longer work.
```

Fixes: #23339
  • Loading branch information
sbc100 committed Jan 15, 2025
1 parent 8e660ed commit 0ee6b6f
Show file tree
Hide file tree
Showing 84 changed files with 146 additions and 121 deletions.
6 changes: 3 additions & 3 deletions src/postamble_minimal.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,10 @@ WebAssembly.instantiate(Module['wasm'], imports).then((output) => {
wasmOffsetConverter = new WasmOffsetConverter(Module['wasm'], output.module);
#endif

#if !DECLARE_ASM_MODULE_EXPORTS
exportWasmSymbols(wasmExports);
#else
#if DECLARE_ASM_MODULE_EXPORTS
assignWasmExports(wasmExports);
#else
exportWasmSymbols(wasmExports);
#endif
#if '$wasmTable' in addedLibraryItems
wasmTable = wasmExports['__indirect_function_table'];
Expand Down
4 changes: 3 additions & 1 deletion src/preamble.js
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,9 @@ function getWasmImports() {
instrumentWasmTableWithAbort();
#endif

#if !DECLARE_ASM_MODULE_EXPORTS
#if DECLARE_ASM_MODULE_EXPORTS
assignWasmExports(wasmExports);
#else
// If we didn't declare the asm exports as top level enties this function
// is in charge of programmatically exporting them on the global object.
exportWasmSymbols(wasmExports);
Expand Down
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_ctors1.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8343
8337
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_ctors1.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20273
20247
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_ctors2.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8327
8321
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_ctors2.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20241
20215
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_except.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9343
9316
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_except.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
24041
23938
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_except_wasm.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8294
8286
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_except_wasm.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20166
20136
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8294
8286
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20166
20136
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_lto.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8357
8348
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_lto.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20348
20312
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_mangle.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9349
9320
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_mangle.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
24041
23938
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_noexcept.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8343
8337
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_noexcept.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20273
20247
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_wasmfs.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3564
3558
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_wasmfs.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7676
7650
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_files_js_fs.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7647
7639
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_files_js_fs.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18820
18794
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_files_wasmfs.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2804
2797
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_files_wasmfs.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5984
5958
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_hello_O0.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7883
7881
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_hello_O0.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20983
20969
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_hello_O1.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2658
2649
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_hello_O1.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6837
6808
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_hello_O2.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2320
2314
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_hello_O2.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4778
4752
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_hello_O3.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2278
2271
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_hello_O3.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4720
4694
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_hello_Os.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2278
2271
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_hello_Os.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4720
4694
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_hello_Oz.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2278
2271
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_hello_Oz.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4720
4694
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_hello_dylink.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5992
5973
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_hello_dylink.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
13241
13167
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_hello_wasmfs.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2278
2271
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_hello_wasmfs.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4720
4694
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1874
1865
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3996
3970
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1912
1906
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4044
4022
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_mem_O3.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2326
2319
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_mem_O3.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4888
4858
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_mem_O3_grow.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2474
2466
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_mem_O3_grow.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5172
5142
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2175
2170
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4581
4563
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_mem_O3_standalone.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2141
2136
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_mem_O3_standalone.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4513
4495
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1898
1890
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4043
4005
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1912
1906
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4044
4022
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1912
1906
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4044
4022
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_64.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1441
1431
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_64.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3058
3041
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_O0.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6449
6446
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_O0.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
17094
17089
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_O1.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1534
1524
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_O1.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3702
3681
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_O2.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1380
1371
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_O2.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2806
2789
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_O3.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1347
1337
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_O3.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2756
2739
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_Os.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1347
1337
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_Os.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2756
2739
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_Oz-ctors.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1338
1329
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_Oz-ctors.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2741
2724
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_Oz.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1347
1337
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_Oz.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2756
2739
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_esm.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1542
1536
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_esm.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3210
3193
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_pthreads.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4186
4140
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_pthreads.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8728
8514
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_wasmfs.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1347
1337
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_wasmfs.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2756
2739
2 changes: 1 addition & 1 deletion test/other/test_unoptimized_code_size.js.size
Original file line number Diff line number Diff line change
@@ -1 +1 @@
52739
52879
2 changes: 1 addition & 1 deletion test/other/test_unoptimized_code_size_no_asserts.js.size
Original file line number Diff line number Diff line change
@@ -1 +1 @@
28487
28607
2 changes: 1 addition & 1 deletion test/other/test_unoptimized_code_size_strict.js.size
Original file line number Diff line number Diff line change
@@ -1 +1 @@
51522
51662
95 changes: 59 additions & 36 deletions tools/emscripten.py
Original file line number Diff line number Diff line change
Expand Up @@ -886,9 +886,14 @@ def can_use_await():
def make_export_wrappers(function_exports):
assert not settings.MINIMAL_RUNTIME

wrappers = []
# When exports are only available asyncronously we generate an extran assignWasmExports
# function. When they are syncronously available we inline the assignment along
# with the declaration.
async_exports = (settings.WASM_ASYNC_COMPILATION and not can_use_await()) or settings.PTHREADS

def install_wrapper(sym):
def install_debug_wrapper(sym):
if not settings.ASSERTIONS:
return False
# 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.
Expand All @@ -901,38 +906,58 @@ def install_wrapper(sym):
# TODO: Look into removing these, and improving our robustness around thread termination.
return sym not in {'__trap', 'pthread_self', '_emscripten_proxy_execute_task_queue'}

for name, types in function_exports.items():
nargs = len(types.params)
mangled = asmjs_mangle(name)
wrapper = 'var %s = ' % mangled

# TODO(sbc): Can we avoid exporting the dynCall_ functions on the module.
def outside_export(mangled):
should_export = settings.EXPORT_KEEPALIVE and mangled in settings.EXPORTED_FUNCTIONS
# TODO(sbc): Can we avoid exporting the dynCall_ functions on the module.
if (name.startswith('dynCall_') and settings.MODULARIZE != 'instance') or should_export:
if settings.MODULARIZE == 'instance':
# Update the export declared at the top level.
wrapper += f" __exp_{mangled} = "
return f" __exp_{mangled}"
else:
exported = "Module['%s'] = " % mangled
else:
exported = ''
wrapper += exported

if settings.ASSERTIONS and install_wrapper(name):
# With assertions enabled we create a wrapper that are calls get routed through, for
# the lifetime of the program.
wrapper += f"createExportWrapper('{name}', {nargs});"
elif (settings.WASM_ASYNC_COMPILATION and not can_use_await()) or settings.PTHREADS:
# With WASM_ASYNC_COMPILATION wrapper will replace the global var and Module var on
# first use.
args = [f'a{i}' for i in range(nargs)]
args = ', '.join(args)
wrapper += f"({args}) => ({mangled} = {exported}wasmExports['{name}'])({args});"
else:
wrapper += f"wasmExports['{name}']"
return "Module['%s']" % mangled

wrappers.append(wrapper)
return wrappers
rtn = []
rtn.append('function assignWasmExports(wasmExports) {')
for name, types in function_exports.items():
# If a debug wrapper was used then we don't need to update anything, we want to
# always use the wrapper, and never the direct export.
if install_debug_wrapper(name):
continue
mangled = asmjs_mangle(name)
wrapper = f' {mangled} = '
additional_export = outside_export(mangled)
if additional_export:
wrapper += additional_export + ' = '
wrapper += f"wasmExports['{name}'];"
rtn.append(wrapper)

rtn.append('}')

rtn.append('')
rtn.append('// Exported wasm functions.')
if async_exports:
rtn.append('// These are declared here but will be remain undefined until async wasm instanatiation is complete.')

if settings.ASSERTIONS:
for name, types in function_exports.items():
mangled = asmjs_mangle(name)
if install_debug_wrapper(name):
# With assertions enabled we create a wrapper that are calls get routed through, for
# the lifetime of the program.
nargs = len(types.params)
additional_export = outside_export(mangled)
if additional_export:
rtn.append(f"var {mangled} = {additional_export} = createExportWrapper('{name}', {nargs});")
else:
rtn.append(f"var {mangled} = createExportWrapper('{name}', {nargs});")
else:
rtn.append(f'var {mangled};')
else:
mangled = [asmjs_mangle(name) for name in function_exports]
sep = ',\n '
rtn.append(f'var {sep.join(mangled)};')

return rtn


def create_receiving(function_exports):
Expand Down Expand Up @@ -986,17 +1011,15 @@ def create_module(receiving, metadata, global_exports, library_symbols):
else:
module.append('var wasmImports = %s;\n' % sending)

module.append(receiving)

if not settings.MINIMAL_RUNTIME:
if settings.WASM_ASYNC_COMPILATION:
if can_use_await():
# In modularize mode the generated code is within a factory function.
module.append("var wasmExports = await createWasm();\n")
else:
module.append("var wasmExports;\ncreateWasm();\n")
if settings.WASM_ASYNC_COMPILATION and can_use_await():
# In modularize mode the generated code is within a factory function.
module.append("var wasmExports = await createWasm();\n")
else:
module.append("var wasmExports = createWasm();\n")
module.append("var wasmExports;\ncreateWasm();\n")

module.append(receiving)
if settings.SUPPORT_LONGJMP == 'emscripten' or not settings.DISABLE_EXCEPTION_CATCHING:
module.append(create_invoke_wrappers(metadata))
else:
Expand Down

0 comments on commit 0ee6b6f

Please sign in to comment.