Skip to content

Commit ad368c1

Browse files
committed
Support JS symbols that are aliases of native ones
We can then use this mechanism to replace the hacky way to we map things like `memory` -> `wasmMemory` and `__indirect_function_table` => `wasmTable`.
1 parent 93cdde9 commit ad368c1

21 files changed

+161
-75
lines changed

src/jsifier.mjs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import {
4040
warningOccured,
4141
localFile,
4242
} from './utility.mjs';
43-
import {LibraryManager, librarySymbols} from './modules.mjs';
43+
import {LibraryManager, librarySymbols, nativeAliases} from './modules.mjs';
4444

4545
const addedLibraryItems = {};
4646

@@ -637,6 +637,7 @@ function(${args}) {
637637
});
638638

639639
let isFunction = false;
640+
let isNativeAlias = false;
640641
let aliasTarget;
641642

642643
const postsetId = symbol + '__postset';
@@ -653,13 +654,19 @@ function(${args}) {
653654

654655
if (typeof snippet == 'string') {
655656
if (snippet[0] != '=') {
656-
if (LibraryManager.library[snippet]) {
657+
if (LibraryManager.library[snippet] || WASM_EXPORTS.has(snippet)) {
657658
// Redirection for aliases. We include the parent, and at runtime
658659
// make ourselves equal to it. This avoid having duplicate
659660
// functions with identical content.
660661
aliasTarget = snippet;
661-
snippet = mangleCSymbolName(aliasTarget);
662-
deps.push(aliasTarget);
662+
if (WASM_EXPORTS.has(snippet)) {
663+
nativeAliases[mangled] = snippet;
664+
snippet = undefined;
665+
isNativeAlias = true;
666+
} else {
667+
deps.push(aliasTarget);
668+
snippet = mangleCSymbolName(aliasTarget);
669+
}
663670
}
664671
}
665672
} else if (typeof snippet == 'object') {
@@ -729,15 +736,11 @@ function(${args}) {
729736
contentText += ';';
730737
}
731738
} else if (typeof snippet == 'undefined') {
732-
// wasmTable is kind of special. In the normal configuration we export
733-
// it from the wasm module under the name `__indirect_function_table`
734-
// but we declare it as an 'undefined' in `libcore.js`.
735-
// Since the normal export mechanism will declare this variable we don't
736-
// want the JS library version of this symbol be declared (otherwise
737-
// it would be a duplicate decl).
738-
// TODO(sbc): This is kind of hacky, we should come up with a better solution.
739-
var isDirectWasmExport = mangled == 'wasmTable';
740-
if (isDirectWasmExport) {
739+
// For JS library functions that are simply aliases of native symbols,
740+
// we don't need to generate anything here. Instead these get included
741+
// and exported alongside native symbols.
742+
// See `create_receiving` in `tools/emscripten.py`.
743+
if (isNativeAlias) {
741744
contentText = '';
742745
} else {
743746
contentText = `var ${mangled};`;
@@ -891,6 +894,7 @@ var proxiedFunctionTable = [
891894
'//FORWARDED_DATA:' +
892895
JSON.stringify({
893896
librarySymbols,
897+
nativeAliases,
894898
warnings: warningOccured(),
895899
asyncFuncs,
896900
libraryDefinitions: LibraryManager.libraryDefinitions,

src/lib/libbootstrap.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ assert(Object.keys(LibraryManager.library).length === 0);
1515
addToLibrary({
1616
$callRuntimeCallbacks: () => {},
1717

18+
$wasmMemory: 'memory',
19+
1820
$ExitStatus: class {
1921
name = 'ExitStatus';
2022
constructor(status) {

src/lib/libcore.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,7 +1637,7 @@ addToLibrary({
16371637
#endif
16381638
}
16391639
}
1640-
1640+
exportAliases(wasmExports);
16411641
},
16421642
#endif
16431643

@@ -2146,8 +2146,6 @@ addToLibrary({
21462146
#endif // MINIMAL_RUNTIME
21472147

21482148
$asmjsMangle: (x) => {
2149-
if (x == 'memory') return 'wasmMemory';
2150-
if (x == '__indirect_function_table') return 'wasmTable';
21512149
if (x == '__main_argc_argv') {
21522150
x = 'main';
21532151
}
@@ -2283,7 +2281,14 @@ addToLibrary({
22832281
});
22842282
`,
22852283
#else
2286-
$wasmTable: undefined,
2284+
$wasmTable: '__indirect_function_table',
2285+
#endif
2286+
2287+
#if IMPORTED_MEMORY
2288+
// This gets defined in src/runtime_init_memory.js
2289+
$wasmMemory: undefined,
2290+
#else
2291+
$wasmMemory: 'memory',
22872292
#endif
22882293

22892294
$getUniqueRunDependency: (id) => {

src/lib/liblegacy.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ legacyFuncs = {
114114
},
115115

116116
// Legacy names for runtime `out`/`err` symbols.
117-
$print: 'out',
118-
$printErr: 'err',
117+
$print: '=out',
118+
$printErr: '=err',
119119

120120
// Converts a JS string to an integer base-10. Despite _s, which
121121
// suggests signaling error handling, this returns NaN on error.

src/modules.mjs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ import {preprocess, processMacros} from './parseTools.mjs';
2929

3030
// List of symbols that were added from the library.
3131
export const librarySymbols = [];
32+
// Map of library symbols which are aliases for native symbols
33+
// e.g. `wasmTable` -> `__indirect_function_table`
34+
export const nativeAliases = {};
3235

3336
const srcDir = fileURLToPath(new URL('.', import.meta.url));
3437
const systemLibdir = path.join(srcDir, 'lib');
@@ -450,7 +453,6 @@ function exportRuntimeSymbols() {
450453
'err',
451454
'callMain',
452455
'abort',
453-
'wasmMemory',
454456
'wasmExports',
455457
'HEAPF32',
456458
'HEAPF64',
@@ -564,13 +566,7 @@ function exportLibrarySymbols() {
564566
assert(MODULARIZE != 'instance');
565567
const results = ['// Begin JS library exports'];
566568
for (const ident of librarySymbols) {
567-
if (EXPORT_ALL || EXPORTED_FUNCTIONS.has(ident)) {
568-
// Special case for wasmTable which can be both a JS library symbol but
569-
// also a wasm export. See isDirectWasmExport in jsifier.mjs.
570-
// FIXME: Remove this hack
571-
if (ident == 'wasmTable' && WASM_EXPORTS.has('__indirect_function_table')) {
572-
continue;
573-
}
569+
if ((EXPORT_ALL || EXPORTED_FUNCTIONS.has(ident)) && !nativeAliases[ident]) {
574570
results.push(exportSymbol(ident));
575571
}
576572
}

src/parseTools.mjs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import {
2424
srcDir,
2525
} from './utility.mjs';
2626

27+
import { nativeAliases } from './modules.mjs';
28+
2729
const FOUR_GB = 4 * 1024 * 1024 * 1024;
2830
const WASM_PAGE_SIZE = 64 * 1024;
2931
const FLOAT_TYPES = new Set(['float', 'double']);
@@ -1155,6 +1157,17 @@ function nodeWWDetection() {
11551157
}
11561158
}
11571159

1160+
function makeExportAliases() {
1161+
var res = ''
1162+
for (var [alias, ex] of Object.entries(nativeAliases)) {
1163+
if (ASSERTIONS) {
1164+
res += ` assert(wasmExports['${ex}'], 'alias target "${ex}" not found in wasmExports');\n`;
1165+
}
1166+
res += ` globalThis['${alias}'] = wasmExports['${ex}'];\n`;
1167+
}
1168+
return res;
1169+
}
1170+
11581171
addToCompileTimeContext({
11591172
ATEXITS,
11601173
ATPRERUNS,
@@ -1204,6 +1217,7 @@ addToCompileTimeContext({
12041217
isSymbolNeeded,
12051218
makeDynCall,
12061219
makeEval,
1220+
makeExportAliases,
12071221
makeGetValue,
12081222
makeHEAPView,
12091223
makeModuleReceive,

src/runtime_common.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,9 @@ if (ENVIRONMENT_IS_NODE) {
174174
#endif // !IMPORTED_MEMORY && ASSERTIONS
175175

176176
#include "memoryprofiler.js"
177+
178+
#if !DECLARE_ASM_MODULE_EXPORTS
179+
function exportAliases(wasmExports) {
180+
{{{ makeExportAliases() }}}
181+
}
182+
#endif

src/runtime_init_memory.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
#error "this file should not be be included when IMPORTED_MEMORY is set"
1010
#endif
1111

12-
var wasmMemory;
13-
1412
// check for full engine support (use string 'subarray' to avoid closure compiler confusion)
1513

1614
function initMemory() {

src/settings_internal.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,3 +273,5 @@ var OUTPUT_FORMAT = '';
273273
// Whether we should load the WASM source map at runtime.
274274
// This is enabled automatically when using -gsource-map with sanitizers.
275275
var LOAD_SOURCE_MAP = false;
276+
277+
var ALIASES = [];

test/codesize/test_codesize_file_preload.expected.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3152,12 +3152,12 @@ Module["FS_createLazyFile"] = FS_createLazyFile;
31523152
// End JS library exports
31533153
// end include: postlibrary.js
31543154
// Imports from the Wasm binary.
3155-
var _main, wasmMemory, wasmTable;
3155+
var _main, memory, __indirect_function_table, wasmMemory;
31563156

31573157
function assignWasmExports(wasmExports) {
31583158
_main = Module["_main"] = wasmExports["d"];
3159-
wasmMemory = wasmExports["b"];
3160-
wasmTable = wasmExports["__indirect_function_table"];
3159+
memory = wasmMemory = wasmExports["b"];
3160+
__indirect_function_table = wasmExports["__indirect_function_table"];
31613161
}
31623162

31633163
var wasmImports = {

0 commit comments

Comments
 (0)