Skip to content

Commit

Permalink
Replace Module["asm"] with wasmExports global
Browse files Browse the repository at this point in the history
This brings the regular runtime closer `MINIMAL_RUNTIME` which uses
the global `asm` to refer to exports object.

As a followup we should consider merging these two symbols.
  • Loading branch information
sbc100 committed Jul 11, 2023
1 parent 8b5c868 commit 3e780ad
Show file tree
Hide file tree
Showing 64 changed files with 180 additions and 168 deletions.
4 changes: 4 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,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 @@ -768,7 +768,7 @@ def install_wrapper(sym):
# With assertions disabled the wrapper will replace the global var and Module var on
# first use.
wrapper += f'''function() {{
return ({mangled} = {exported}Module['asm']['{name}']).apply(null, arguments);
return ({mangled} = {exported}wasmExports['{name}']).apply(null, arguments);
}};
'''
else:
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 @@ -336,7 +336,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
1 change: 1 addition & 0 deletions src/modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ function exportRuntime() {
'abort',
'keepRuntimeAlive',
'wasmMemory',
'wasmExports',
];

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

function maybeExport(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;
{{{ maybeExport('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'];
{{{ maybeExport('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'];
{{{ maybeExport('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 @@ -18,21 +18,21 @@ var expD5 = asm["expD5"];
var expD6;

var expI1 = Module["expI1"] = function() {
return (expI1 = Module["expI1"] = Module["asm"]["expI1"]).apply(null, arguments);
return (expI1 = Module["expI1"] = wasmExports["expI1"]).apply(null, arguments);
};

var expI2 = Module["expI2"] = function() {
return (expI2 = Module["expI2"] = Module["asm"]["expI2"]).apply(null, arguments);
return (expI2 = Module["expI2"] = wasmExports["expI2"]).apply(null, arguments);
};

var expI3 = Module["expI3"] = function() {
return (expI3 = Module["expI3"] = Module["asm"]["expI3"]).apply(null, arguments);
return (expI3 = Module["expI3"] = wasmExports["expI3"]).apply(null, arguments);
};

var expI4;

var expI5 = function() {
return (expI5 = Module["asm"]["expI5"]).apply(null, arguments);
return (expI5 = wasmExports["expI5"]).apply(null, arguments);
};

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 @@ -12,23 +12,23 @@ var expD6 = asm['expD6'];

// exports gotten indirectly (async compilation
var expI1 = Module['expI1'] = (function() {
return (expI1 = Module['expI1'] = Module['asm']['expI1']).apply(null, arguments);
return (expI1 = Module['expI1'] = wasmExports['expI1']).apply(null, arguments);
});
var expI2 = Module['expI2'] = (function() {
return (expI2 = Module['expI2'] = Module['asm']['expI2']).apply(null, arguments);
return (expI2 = Module['expI2'] = wasmExports['expI2']).apply(null, arguments);
});
var expI3 = Module['expI3'] = (function() {
return (expI3 = Module['expI3'] = Module['asm']['expI3']).apply(null, arguments);
return (expI3 = Module['expI3'] = wasmExports['expI3']).apply(null, arguments);
});
var expI4 = Module['expI4'] = (function() {
return (expI4 = Module['expI4'] = Module['asm']['expI4']).apply(null, arguments);
return (expI4 = Module['expI4'] = wasmExports['expI4']).apply(null, arguments);
});
// Like above, but not exported on the Module
var expI5 = (function() {
return (expI5 = Module['asm']['expI5']).apply(null, arguments);
return (expI5 = wasmExports['expI5']).apply(null, arguments);
});
var expI6 = (function() {
return (expI6 = Module['asm']['expI6']).apply(null, arguments);
return (expI6 = wasmExports['expI6']).apply(null, arguments);
});

// add uses for some of them, leave *4 as non-roots
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 @@ -54,20 +54,20 @@ var expD5 = asm['expD5'];

// exports gotten indirectly (async compilation
var expI1 = Module['expI1'] = function() {
return (expI1 = Module['expI1'] = Module['asm']['expI1']).apply(null, arguments);
return (expI1 = Module['expI1'] = wasmExports['expI1']).apply(null, arguments);
};
var expI2 = Module['expI2'] = function() {
return (expI2 = Module['expI2'] = Module['asm']['expI2']).apply(null, arguments);
return (expI2 = Module['expI2'] = wasmExports['expI2']).apply(null, arguments);
};
var expI3 = Module['expI3'] = function() {
return (expI3 = Module['expI3'] = Module['asm']['expI3']).apply(null, arguments);
return (expI3 = Module['expI3'] = wasmExports['expI3']).apply(null, arguments);
};
var expI4 = Module['expI4'] = function() {
return (expI4 = Module['expI4'] = Module['asm']['expI4']).apply(null, arguments);
return (expI4 = Module['expI4'] = wasmExports['expI4']).apply(null, arguments);
};
// Same as above but not export on the Module.
var expI5 = function() {
return (expI5 = Module['asm']['expI5']).apply(null, arguments);
return (expI5 = wasmExports['expI5']).apply(null, arguments);
};

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

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

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

// dyncalls
var dynCall_v = Module["dynCall_v"] = function() { return Module["asm"]["dynCall_v"].apply(null, arguments) };
var dynCall_vi = Module["dynCall_vi"] = function() { return Module["asm"]["dynCall_vi"].apply(null, arguments) };
var dynCall_vii = Module["dynCall_vii"] = function() { return Module["asm"]["dynCall_vii"].apply(null, arguments) };
var dynCall_viii = Module["dynCall_viii"] = function() { return Module["asm"]["dynCall_viii"].apply(null, arguments) };
var dynCall_v = Module["dynCall_v"] = function() { return wasmExports["dynCall_v"].apply(null, arguments) };
var dynCall_vi = Module["dynCall_vi"] = function() { return wasmExports["dynCall_vi"].apply(null, arguments) };
var dynCall_vii = Module["dynCall_vii"] = function() { return wasmExports["dynCall_vii"].apply(null, arguments) };
var dynCall_viii = Module["dynCall_viii"] = function() { return wasmExports["dynCall_viii"].apply(null, arguments) };

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"] = function() { return Module["asm"]["dynCall_v"].apply(null, arguments) };
var dynCall_vi = Module["dynCall_vi"] = function() { return Module["asm"]["dynCall_vi"].apply(null, arguments) };
var dynCall_vii = Module["dynCall_vii"] = function() { return Module["asm"]["dynCall_vii"].apply(null, arguments) };
var dynCall_viii = Module["dynCall_viii"] = function() { return Module["asm"]["dynCall_viii"].apply(null, arguments) };
var dynCall_v = Module["dynCall_v"] = function() { return wasmExports["dynCall_v"].apply(null, arguments) };
var dynCall_vi = Module["dynCall_vi"] = function() { return wasmExports["dynCall_vi"].apply(null, arguments) };
var dynCall_vii = Module["dynCall_vii"] = function() { return wasmExports["dynCall_vii"].apply(null, arguments) };
var dynCall_viii = Module["dynCall_viii"] = function() { return wasmExports["dynCall_viii"].apply(null, arguments) };

// 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"] = function() { return Module["asm"]["dynCall_v"].apply(null, arguments) };
var dynCall_vi = Module["dynCall_vi"] = function() { return Module["asm"]["dynCall_vi"].apply(null, arguments) };
var dynCall_vii = Module["dynCall_vii"] = function() { return Module["asm"]["dynCall_vii"].apply(null, arguments) };
var dynCall_viii = Module["dynCall_viii"] = function() { return Module["asm"]["dynCall_viii"].apply(null, arguments) };
var dynCall_v = Module["dynCall_v"] = function() { return wasmExports["dynCall_v"].apply(null, arguments) };
var dynCall_vi = Module["dynCall_vi"] = function() { return wasmExports["dynCall_vi"].apply(null, arguments) };
var dynCall_vii = Module["dynCall_vii"] = function() { return wasmExports["dynCall_vii"].apply(null, arguments) };
var dynCall_viii = Module["dynCall_viii"] = function() { return wasmExports["dynCall_viii"].apply(null, arguments) };

// 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"] = function() { return Module["asm"]["dynCall_v"].apply(null, arguments) };
var dynCall_vi = Module["dynCall_vi"] = function() { return Module["asm"]["dynCall_vi"].apply(null, arguments) };
var dynCall_vii = Module["dynCall_vii"] = function() { return Module["asm"]["dynCall_vii"].apply(null, arguments) };
var dynCall_viii = Module["dynCall_viii"] = function() { return Module["asm"]["dynCall_viii"].apply(null, arguments) };
var dynCall_v = Module["dynCall_v"] = function() { return wasmExports["dynCall_v"].apply(null, arguments) };
var dynCall_vi = Module["dynCall_vi"] = function() { return wasmExports["dynCall_vi"].apply(null, arguments) };
var dynCall_vii = Module["dynCall_vii"] = function() { return wasmExports["dynCall_vii"].apply(null, arguments) };
var dynCall_viii = Module["dynCall_viii"] = function() { return wasmExports["dynCall_viii"].apply(null, arguments) };

// a dynamic dynCall
function dynCall(sig) {
Expand Down
Loading

0 comments on commit 3e780ad

Please sign in to comment.