Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace Module["asm"] with wasmExports global #19816

Merged
merged 1 commit into from
Jul 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ See docs/process.md for more on how version tagging works.
- The internal `read_` and `readAsync` functions no longer handle date URIs.
This only effects builds that use `-sSINGLE_FILE` or `--memory-init-file`.
(#19792)
- The `asm` property of the Module object (which held the raw exports of the
wasm module) has been removed. Internally, this is now accessed via the
`wasmExports` global. If necessary, it is possible to export `wasmExports`
on the Module object using `-sEXPORTED_RUNTIME_METHODS=wasmExports`. (#19816)

3.1.43 - 07/10/23
-----------------
Expand Down
2 changes: 1 addition & 1 deletion emscripten.py
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ def install_wrapper(sym):
# first use.
args = [f'a{i}' for i in range(nargs)]
args = ', '.join(args)
wrapper += f"({args}) => ({mangled} = {exported}Module['asm']['{name}'])({args});"
wrapper += f"({args}) => ({mangled} = {exported}wasmExports['{name}'])({args});"
else:
wrapper += 'asm["%s"]' % name

Expand Down
4 changes: 2 additions & 2 deletions site/source/docs/optimizing/Module-Splitting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ included in the profile.
Here’s the function to write the profile and our new main function::

EM_JS(void, write_profile, (), {
var __write_profile = Module['asm']['__write_profile'];
var __write_profile = wasmExports['__write_profile'];
if (__write_profile) {

// Get the size of the profile and allocate a buffer for it.
Expand Down Expand Up @@ -338,7 +338,7 @@ be called either.

When eagerly instantiating the secondary module, the imports object should be::

{'primary': Module['asm']}
{'primary': wasmExports}

Debugging
---------
Expand Down
8 changes: 4 additions & 4 deletions src/library_async.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,9 @@ mergeInto(LibraryManager.library, {
getDataRewindFunc: function(ptr) {
var id = {{{ makeGetValue('ptr', C_STRUCTS.asyncify_data_s.rewind_id, 'i32') }}};
var name = Asyncify.callStackIdToName[id];
var func = Module['asm'][name];
var func = wasmExports[name];
#if RELOCATABLE
// Exported functions in side modules are not listed in `Module['asm']`,
// Exported functions in side modules are not listed in `wasmExports`,
// So we should use `resolveGlobalSymbol` helper function, which is defined in `library_dylink.js`.
if (!func) {
func = resolveGlobalSymbol(name, false).sym;
Expand Down Expand Up @@ -522,8 +522,8 @@ mergeInto(LibraryManager.library, {
_load_secondary_module__sig: 'v',
_load_secondary_module: async function() {
// Mark the module as loading for the wasm module (so it doesn't try to load it again).
Module['asm']['load_secondary_module_status'].value = 1;
var imports = {'primary': Module['asm']};
wasmExports['load_secondary_module_status'].value = 1;
var imports = {'primary': wasmExports};
// Replace '.wasm' suffix with '.deferred.wasm'.
var deferred = wasmBinaryFile.slice(0, -5) + '.deferred.wasm';
await new Promise((resolve) => {
Expand Down
2 changes: 1 addition & 1 deletion src/library_exceptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ var LibraryExceptions = {
#if RELOCATABLE
return ___cpp_exception; // defined in library.js
#else
return Module['asm']['__cpp_exception'];
return wasmExports['__cpp_exception'];
#endif
},

Expand Down
2 changes: 1 addition & 1 deletion src/library_exports.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ mergeInto(LibraryManager.library, {
var exportedFunc = asm[name];
#else
// In regular runtime, exports are available on the Module object.
var exportedFunc = Module['asm'][name];
var exportedFunc = wasmExports[name];
#endif
if (exportedFunc) {
// Record the created function pointer to each function object,
Expand Down
2 changes: 2 additions & 0 deletions src/modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,8 @@ function exportRuntime() {
'abort',
'keepRuntimeAlive',
'wasmMemory',
'wasmTable',
'wasmExports',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed? The explicit maybeExport in the proper places handles it, no?

];

// These are actually native wasm functions these days but we allow exporting
Expand Down
10 changes: 10 additions & 0 deletions src/parseTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,16 @@ function hasExportedSymbol(sym) {
return WASM_EXPORTS.has(sym);
}

// Called when global runtime symbols such as wasmMemory, wasmExports and
// wasmTable are set. In this case we maybe need to re-export them on the
// Module object.
function receivedSymbol(sym) {
if (EXPORTED_RUNTIME_METHODS.includes(sym)) {
return `Module['${sym}'] = ${sym};`
}
return '';
}

// JS API I64 param handling: if we have BigInt support, the ABI is simple,
// it is a BigInt. Otherwise, we legalize into pairs of i32s.
function defineI64Param(name) {
Expand Down
2 changes: 1 addition & 1 deletion src/postamble_minimal.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ WebAssembly.instantiate(Module['wasm'], imports).then((output) => {

#if !LibraryManager.has('library_exports.js') && !EMBIND
// If not using the emscripten_get_exported_function() API or embind, keep the
// 'asm' exports variable in local scope to this instantiate function to save
// `asm` exports variable in local scope to this instantiate function to save
// code size. (otherwise access it without to export it to outer scope)
var
#endif
Expand Down
24 changes: 14 additions & 10 deletions src/preamble.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ if (typeof WebAssembly != 'object') {
// Wasm globals

var wasmMemory;
var wasmExports;

#if SHARED_MEMORY
// For sending to workers.
Expand Down Expand Up @@ -471,7 +472,7 @@ function abort(what) {
#if WASM_EXCEPTIONS == 1
// See above, in the meantime, we resort to wasm code for trapping.
//
// In case abort() is called before the module is initialized, Module['asm']
// In case abort() is called before the module is initialized, wasmExports
// and its exported '__trap' function is not available, in which case we throw
// a RuntimeError.
//
Expand Down Expand Up @@ -527,7 +528,7 @@ function createExportWrapper(name) {
#if EXIT_RUNTIME
assert(!runtimeExited, `native function \`${name}\` called after runtime exit (use NO_EXIT_RUNTIME to keep it alive after main() exits)`);
#endif
var f = Module['asm'][name];
var f = wasmExports[name];
assert(f, `exported native function \`${name}\` not found`);
return f.apply(null, arguments);
};
Expand Down Expand Up @@ -714,7 +715,7 @@ var splitModuleProxyHandler = {
throw new Error('Placeholder function "' + prop + '" should not be called when using JSPI.');
#else
err('placeholder function called: ' + prop);
var imports = {'primary': Module['asm']};
var imports = {'primary': wasmExports};
// Replace '.wasm' suffix with '.deferred.wasm'.
var deferred = wasmBinaryFile.slice(0, -5) + '.deferred.wasm'
loadSplitModule(deferred, imports, prop);
Expand Down Expand Up @@ -979,18 +980,20 @@ function createWasm() {
exports = applySignatureConversions(exports);
#endif

Module['asm'] = exports;
wasmExports = exports;
{{{ receivedSymbol('wasmExports') }}}

#if PTHREADS
#if MAIN_MODULE
registerTLSInit(Module['asm']['_emscripten_tls_init'], instance.exports, metadata);
registerTLSInit(wasmExports['_emscripten_tls_init'], instance.exports, metadata);
#else
registerTLSInit(Module['asm']['_emscripten_tls_init']);
registerTLSInit(wasmExports['_emscripten_tls_init']);
#endif
#endif

#if !IMPORTED_MEMORY
wasmMemory = Module['asm']['memory'];
wasmMemory = wasmExports['memory'];
{{{ receivedSymbol('wasmMemory') }}}
#if ASSERTIONS
assert(wasmMemory, "memory not found in wasm exports");
// This assertion doesn't hold when emscripten is run in --post-link
Expand All @@ -1005,7 +1008,8 @@ function createWasm() {
#endif

#if !RELOCATABLE
wasmTable = Module['asm']['__indirect_function_table'];
wasmTable = wasmExports['__indirect_function_table'];
{{{ receivedSymbol('wasmTable') }}}
#if ASSERTIONS && !PURE_WASI
assert(wasmTable, "table not found in wasm exports");
#endif
Expand All @@ -1019,11 +1023,11 @@ function createWasm() {
#endif

#if hasExportedSymbol('__wasm_call_ctors')
addOnInit(Module['asm']['__wasm_call_ctors']);
addOnInit(wasmExports['__wasm_call_ctors']);
#endif

#if hasExportedSymbol('__wasm_apply_data_relocs')
__RELOC_FUNCS__.push(Module['asm']['__wasm_apply_data_relocs']);
__RELOC_FUNCS__.push(wasmExports['__wasm_apply_data_relocs']);
#endif

#if ABORT_ON_WASM_EXCEPTIONS
Expand Down
8 changes: 5 additions & 3 deletions src/runtime_debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,22 @@

#if ASSERTIONS

function legacyModuleProp(prop, newName) {
function legacyModuleProp(prop, newName, incomming=true) {
if (!Object.getOwnPropertyDescriptor(Module, prop)) {
Object.defineProperty(Module, prop, {
configurable: true,
get() {
abort('Module.' + prop + ' has been replaced with plain ' + newName + ' (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)');
let extra = incomming ? ' (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)' : '';
abort(`\`Module.${prop}\` has been replaced by \`${newName}\`` + extra);

}
});
}
}

function ignoredModuleProp(prop) {
if (Object.getOwnPropertyDescriptor(Module, prop)) {
abort('`Module.' + prop + '` was supplied but `' + prop + '` not included in INCOMING_MODULE_JS_API');
abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/shell.js
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,7 @@ assert(typeof Module['readAsync'] == 'undefined', 'Module.readAsync option was r
assert(typeof Module['readBinary'] == 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)');
assert(typeof Module['setWindowTitle'] == 'undefined', 'Module.setWindowTitle option was removed (modify setWindowTitle in JS)');
assert(typeof Module['TOTAL_MEMORY'] == 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY');
{{{ makeRemovedModuleAPIAssert('asm', 'wasmExports', false) }}}
{{{ makeRemovedModuleAPIAssert('read', 'read_') }}}
{{{ makeRemovedModuleAPIAssert('readAsync') }}}
{{{ makeRemovedModuleAPIAssert('readBinary') }}}
Expand Down
8 changes: 4 additions & 4 deletions test/optimizer/applyDCEGraphRemovals-output.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ var expD5 = asm["expD5"];

var expD6;

var expI1 = Module["expI1"] = () => (expI1 = Module["expI1"] = Module["asm"]["expI1"])();
var expI1 = Module["expI1"] = () => (expI1 = Module["expI1"] = wasmExports["expI1"])();

var expI2 = Module["expI2"] = () => (expI2 = Module["expI2"] = Module["asm"]["expI2"])();
var expI2 = Module["expI2"] = () => (expI2 = Module["expI2"] = wasmExports["expI2"])();

var expI3 = Module["expI3"] = () => (expI3 = Module["expI3"] = Module["asm"]["expI3"])();
var expI3 = Module["expI3"] = () => (expI3 = Module["expI3"] = wasmExports["expI3"])();

var expI4;

var expI5 = () => (expI5 = Module["asm"]["expI5"])();
var expI5 = () => (expI5 = wasmExports["expI5"])();

var expI6;

Expand Down
12 changes: 6 additions & 6 deletions test/optimizer/applyDCEGraphRemovals.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ var expD5 = asm['expD5'];
var expD6 = asm['expD6'];

// exports gotten indirectly (async compilation
var expI1 = Module['expI1'] = () => (expI1 = Module['expI1'] = Module['asm']['expI1'])();
var expI2 = Module['expI2'] = () => (expI2 = Module['expI2'] = Module['asm']['expI2'])();
var expI3 = Module['expI3'] = () => (expI3 = Module['expI3'] = Module['asm']['expI3'])();
var expI4 = Module['expI4'] = () => (expI4 = Module['expI4'] = Module['asm']['expI4'])();
var expI1 = Module['expI1'] = () => (expI1 = Module['expI1'] = wasmExports['expI1'])();
var expI2 = Module['expI2'] = () => (expI2 = Module['expI2'] = wasmExports['expI2'])();
var expI3 = Module['expI3'] = () => (expI3 = Module['expI3'] = wasmExports['expI3'])();
var expI4 = Module['expI4'] = () => (expI4 = Module['expI4'] = wasmExports['expI4'])();

// Like above, but not exported on the Module
var expI5 = () => (expI5 = Module['asm']['expI5'])();
var expI6 = () => (expI6 = Module['asm']['expI6'])();
var expI5 = () => (expI5 = wasmExports['expI5'])();
var expI6 = () => (expI6 = wasmExports['expI6'])();

// add uses for some of them, leave *4 as non-roots
expD1;
Expand Down
2 changes: 1 addition & 1 deletion test/optimizer/applyImportAndExportNameChanges-output.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ var wasmImports = {
var expD1 = Module["expD1"] = asm["c"];

var expI1 = Module["expI1"] = function() {
return Module["asm"]["d"].apply(null, arguments);
return wasmExports["d"].apply(null, arguments);
};
2 changes: 1 addition & 1 deletion test/optimizer/applyImportAndExportNameChanges.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ var expD1 = Module['expD1'] = asm['expD1'];

// exports gotten indirectly (async compilation
var expI1 = Module['expI1'] = (function() {
return Module['asm']['expI1'].apply(null, arguments);
return wasmExports['expI1'].apply(null, arguments);
});

// EXTRA_INFO: { "mapping": {"save1" : "a", "number": "A", "expD1": "c", "expI1": "d", "__wasm_call_ctors": "e", "stackRestore": "h", "stackAlloc": "g", "__syscall140": "d", "main": "f", "__syscall146": "q", "__syscall54": "c", "__syscall6": "b" }}
Expand Down
20 changes: 10 additions & 10 deletions test/optimizer/emitDCEGraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ var expD4 = Module['expD4'] = asm['expD4'];
var expD5 = asm['expD5'];

// exports gotten indirectly (async compilation
var expI1 = Module['expI1'] = () => (expI1 = Module['expI1'] = Module['asm']['expI1'])();
var expI2 = Module['expI2'] = () => (expI2 = Module['expI2'] = Module['asm']['expI2'])();
var expI3 = Module['expI3'] = () => (expI3 = Module['expI3'] = Module['asm']['expI3'])();
var expI4 = Module['expI4'] = () => (expI4 = Module['expI4'] = Module['asm']['expI4'])();
var expI1 = Module['expI1'] = () => (expI1 = Module['expI1'] = wasmExports['expI1'])();
var expI2 = Module['expI2'] = () => (expI2 = Module['expI2'] = wasmExports['expI2'])();
var expI3 = Module['expI3'] = () => (expI3 = Module['expI3'] = wasmExports['expI3'])();
var expI4 = Module['expI4'] = () => (expI4 = Module['expI4'] = wasmExports['expI4'])();

// Same as above but not export on the Module.
var expI5 = () => (expI5 = Module['asm']['expI5'])();
var expI5 = () => (expI5 = wasmExports['expI5'])();

// add uses for some of them
expD1;
Expand All @@ -68,7 +68,7 @@ asm['expD3'];

expI1;
Module['expI2'];
Module['asm']['expI3'];
wasmExports['expI3'];

// deep uses, that we can't scan
function usedFromDeep() {
Expand All @@ -86,10 +86,10 @@ var func = function() {
};

// dyncalls
var dynCall_v = Module["dynCall_v"] = () => Module["asm"]["dynCall_v"]();
var dynCall_vi = Module["dynCall_vi"] = () => Module["asm"]["dynCall_vi"]();
var dynCall_vii = Module["dynCall_vii"] = () => Module["asm"]["dynCall_vii"]();
var dynCall_viii = Module["dynCall_viii"] = () => Module["asm"]["dynCall_viii"]();
var dynCall_v = Module["dynCall_v"] = () => wasmExports["dynCall_v"]();
var dynCall_vi = Module["dynCall_vi"] = () => wasmExports["dynCall_vi"]();
var dynCall_vii = Module["dynCall_vii"] = () => wasmExports["dynCall_vii"]();
var dynCall_viii = Module["dynCall_viii"] = () => wasmExports["dynCall_viii"]();

dynCall_v(ptr); // use directly
Module['dynCall_vi'](ptr, 1); // use on module
Expand Down
8 changes: 4 additions & 4 deletions test/optimizer/emitDCEGraph2.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// dyncalls
var dynCall_v = Module["dynCall_v"] = () => Module["asm"]["dynCall_v"]();
var dynCall_vi = Module["dynCall_vi"] = () => Module["asm"]["dynCall_vi"]();
var dynCall_vii = Module["dynCall_vii"] = () => Module["asm"]["dynCall_vii"]();
var dynCall_viii = Module["dynCall_viii"] = () => Module["asm"]["dynCall_viii"]();
var dynCall_v = Module["dynCall_v"] = () => wasmExports["dynCall_v"]();
var dynCall_vi = Module["dynCall_vi"] = () => wasmExports["dynCall_vi"]();
var dynCall_vii = Module["dynCall_vii"] = () => wasmExports["dynCall_vii"]();
var dynCall_viii = Module["dynCall_viii"] = () => wasmExports["dynCall_viii"]();

// a dynamic dynCall
function dynCall(sig) {
Expand Down
8 changes: 4 additions & 4 deletions test/optimizer/emitDCEGraph3.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// dyncalls
var dynCall_v = Module["dynCall_v"] = () => Module["asm"]["dynCall_v"]();
var dynCall_vi = Module["dynCall_vi"] = () => Module["asm"]["dynCall_vi"]();
var dynCall_vii = Module["dynCall_vii"] = () => Module["asm"]["dynCall_vii"]();
var dynCall_viii = Module["dynCall_viii"] = () => Module["asm"]["dynCall_viii"]();
var dynCall_v = Module["dynCall_v"] = () => wasmExports["dynCall_v"]();
var dynCall_vi = Module["dynCall_vi"] = () => wasmExports["dynCall_vi"]();
var dynCall_vii = Module["dynCall_vii"] = () => wasmExports["dynCall_vii"]();
var dynCall_viii = Module["dynCall_viii"] = () => wasmExports["dynCall_viii"]();

// a dynamic dynCall
function dynCall(sig) {
Expand Down
8 changes: 4 additions & 4 deletions test/optimizer/emitDCEGraph4.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// dyncalls
var dynCall_v = Module["dynCall_v"] = () => Module["asm"]["dynCall_v"]();
var dynCall_vi = Module["dynCall_vi"] = () => Module["asm"]["dynCall_vi"]();
var dynCall_vii = Module["dynCall_vii"] = () => Module["asm"]["dynCall_vii"]();
var dynCall_viii = Module["dynCall_viii"] = () => Module["asm"]["dynCall_viii"]();
var dynCall_v = Module["dynCall_v"] = () => wasmExports["dynCall_v"]();
var dynCall_vi = Module["dynCall_vi"] = () => wasmExports["dynCall_vi"]();
var dynCall_vii = Module["dynCall_vii"] = () => wasmExports["dynCall_vii"]();
var dynCall_viii = Module["dynCall_viii"] = () => wasmExports["dynCall_viii"]();

// a dynamic dynCall
function dynCall(sig) {
Expand Down
8 changes: 4 additions & 4 deletions test/optimizer/emitDCEGraph5.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// wasm backend notation has one fewer _ in the wasm
__GLOBAL__I_000101(); // var use
var __GLOBAL__I_000101 = Module["__GLOBAL__I_000101"] = () => Module["asm"]["_GLOBAL__I_000101"]();
var __GLOBAL__I_000101 = Module["__GLOBAL__I_000101"] = () => wasmExports["_GLOBAL__I_000101"]();

__ATINIT__.push({ func: function() { __GLOBAL__I_iostream() } }); // var use inside other scope
var __GLOBAL__I_iostream = Module["__GLOBAL__I_iostream"] = () => Module["asm"]["_GLOBAL__I_iostream.cpp"]();
var __GLOBAL__I_iostream = Module["__GLOBAL__I_iostream"] = () => wasmExports["_GLOBAL__I_iostream.cpp"]();

Module["__DUB"](); // module use
var __DUB = Module["__DUB"] = () => Module["asm"]["_DUB"]();
var __DUB = Module["__DUB"] = () => wasmExports["_DUB"]();

var __UNUSED = Module["__UNUSED"] = () => Module["asm"]["_UNUSED"]();
var __UNUSED = Module["__UNUSED"] = () => wasmExports["_UNUSED"]();

var wasmImports = {
};
Expand Down
2 changes: 1 addition & 1 deletion test/other/metadce/test_metadce_cxx_ctors1.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
25162
25131
2 changes: 1 addition & 1 deletion test/other/metadce/test_metadce_cxx_ctors2.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
25126
25099
2 changes: 1 addition & 1 deletion test/other/metadce/test_metadce_cxx_except.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
29381
29309
Loading