Skip to content

Commit ab94f82

Browse files
committed
Optimize makeDynCall to use dynCall_xx function directly where needed
Now the runtime `dynCall` is only used in places where the signature is not known at compile time, such as embind or (the internally unused) `getFuncWrapper`. Move `getDynCaller` into embind.js which is the only place it was used.
1 parent 5dc1e7c commit ab94f82

File tree

7 files changed

+24
-18
lines changed

7 files changed

+24
-18
lines changed

emcc.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,7 +1381,6 @@ def filter_out_duplicate_dynamic_libs(inputs):
13811381
# See: https://github.com/emscripten-core/emscripten/issues/12065
13821382
# See: https://github.com/emscripten-core/emscripten/issues/12066
13831383
shared.Settings.USE_LEGACY_DYNCALLS = 1
1384-
shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$getDynCaller']
13851384
shared.Settings.EXPORTED_FUNCTIONS += ['_emscripten_stack_get_base',
13861385
'_emscripten_stack_get_end',
13871386
'_emscripten_stack_set_limits']
@@ -1614,18 +1613,12 @@ def filter_out_duplicate_dynamic_libs(inputs):
16141613
if not shared.Settings.MINIMAL_RUNTIME or shared.Settings.EXIT_RUNTIME:
16151614
# MINIMAL_RUNTIME only needs callRuntimeCallbacks in certain cases, but the normal runtime
16161615
# always does.
1617-
shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$callRuntimeCallbacks', '$dynCall']
1616+
shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$callRuntimeCallbacks']
16181617

16191618
if shared.Settings.USE_PTHREADS:
16201619
# memalign is used to ensure allocated thread stacks are aligned.
16211620
shared.Settings.EXPORTED_FUNCTIONS += ['_memalign']
16221621

1623-
# dynCall is used to call pthread entry points in worker.js (as
1624-
# metadce does not consider worker.js, which is external, we must
1625-
# consider it an export, i.e., one which can never be removed).
1626-
shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$dynCall']
1627-
shared.Settings.EXPORTED_FUNCTIONS += ['dynCall']
1628-
16291622
if shared.Settings.MINIMAL_RUNTIME:
16301623
building.user_requested_exports += ['exit']
16311624

@@ -1638,6 +1631,7 @@ def include_and_export(name):
16381631
shared.Settings.EXPORTED_FUNCTIONS += [name]
16391632

16401633
include_and_export('establishStackSpace')
1634+
include_and_export('invokeEntryPoint')
16411635
if not shared.Settings.MINIMAL_RUNTIME:
16421636
# noExitRuntime does not apply to MINIMAL_RUNTIME.
16431637
include_and_export('getNoExitRuntime')

src/library.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3727,7 +3727,7 @@ LibraryManager.library = {
37273727
},
37283728
#endif
37293729

3730-
$dynCall: function (sig, ptr, args) {
3730+
$dynCall: function(sig, ptr, args) {
37313731
#if USE_LEGACY_DYNCALLS
37323732
return dynCallLegacy(sig, ptr, args);
37333733
#else

src/library_browser.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,10 +1105,9 @@ var LibraryBrowser = {
11051105
},
11061106

11071107
// TODO: currently not callable from a pthread, but immediately calls onerror() if not on main thread.
1108-
emscripten_async_load_script__deps: ['$getFuncWrapper'],
11091108
emscripten_async_load_script: function(url, onload, onerror) {
1110-
onload = getFuncWrapper(onload, 'v');
1111-
onerror = getFuncWrapper(onerror, 'v');
1109+
onload = {{{ makeDynCall('v', 'onload') }}};
1110+
onerror = {{{ makeDynCall('v', 'onerror') }}};
11121111

11131112
#if USE_PTHREADS
11141113
if (ENVIRONMENT_IS_PTHREAD) {
@@ -1197,7 +1196,7 @@ var LibraryBrowser = {
11971196
emscripten_set_main_loop__deps: ['$setMainLoop'],
11981197
emscripten_set_main_loop__docs: '/** @param {number|boolean=} noSetTiming */',
11991198
emscripten_set_main_loop: function(func, fps, simulateInfiniteLoop, arg, noSetTiming) {
1200-
var browserIterationFunc = function() { {{{ makeDynCall('v', 'func') }}}(); };
1199+
var browserIterationFunc = {{{ makeDynCall('v', 'func') }}};
12011200
setMainLoop(browserIterationFunc, fps, simulateInfiniteLoop, arg, noSetTiming);
12021201
},
12031202

@@ -1519,7 +1518,6 @@ var LibraryBrowser = {
15191518
Browser.workers[id] = null;
15201519
},
15211520

1522-
emscripten_call_worker__deps: ['$getFuncWrapper'],
15231521
emscripten_call_worker__proxy: 'sync',
15241522
emscripten_call_worker__sig: 'viiiiii',
15251523
emscripten_call_worker: function(id, funcName, data, size, callback, arg) {
@@ -1531,7 +1529,7 @@ var LibraryBrowser = {
15311529
if (callback) {
15321530
callbackId = info.callbacks.length;
15331531
info.callbacks.push({
1534-
func: getFuncWrapper(callback, 'viii'),
1532+
func: {{{ makeDynCall('viii', 'callback') }}},
15351533
arg: arg
15361534
});
15371535
info.awaited++;

src/library_pthread.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,10 @@ var LibraryPThread = {
14241424
return noExitRuntime;
14251425
},
14261426

1427+
$invokeEntryPoint: function(ptr, arg) {
1428+
return {{{ makeDynCall('ii', 'ptr') }}}(arg);
1429+
},
1430+
14271431
// When using postMessage to send an object, it is processed by the structured clone algorithm.
14281432
// The prototype, and hence methods, on that object is then lost. This function adds back the lost prototype.
14291433
// This does not work with nested objects that has prototypes, but it suffices for WasmSourceMap and WasmOffsetConverter.

src/parseTools.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,17 @@ function makeDynCall(sig, funcPtr) {
985985
}
986986
}
987987
if (USE_LEGACY_DYNCALLS) {
988-
return `getDynCaller("${sig}", ${funcPtr})`;
988+
let dyncall = exportedAsmFunc(`dynCall_${sig}`)
989+
if (sig.length > 1) {
990+
let args = [];
991+
for (let i = 1; i < sig.length; ++i) {
992+
args.push(`a${i}`);
993+
}
994+
args = args.join(', ');
995+
return `(function(${args}) { ${dyncall}.apply(null, [${funcPtr}, ${args}]); })`;
996+
} else {
997+
return `(function() { ${dyncall}.call(null, ${funcPtr}); })`;
998+
}
989999
} else {
9901000
return `wasmTable.get(${funcPtr})`;
9911001
}

src/worker.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ this.onmessage = function(e) {
188188
// enable that to work. If you find the following line to crash, either change the signature
189189
// to "proper" void *ThreadMain(void *arg) form, or try linking with the Emscripten linker
190190
// flag -s EMULATE_FUNCTION_POINTER_CASTS=1 to add in emulation for this x86 ABI extension.
191-
var result = Module['dynCall']('ii', e.data.start_routine, [e.data.arg]);
191+
var result = Module['invokeEntryPoint'](e.data.start_routine, e.data.arg);
192192

193193
#if STACK_OVERFLOW_CHECK
194194
Module['checkStackCookie']();

tools/ports/sdl2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def clear(ports, settings, shared):
9090

9191

9292
def process_dependencies(settings):
93-
settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$autoResumeAudioContext']
93+
settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$autoResumeAudioContext', '$dynCall']
9494

9595

9696
def process_args(ports):

0 commit comments

Comments
 (0)