Skip to content

Commit 953aded

Browse files
authored
Part two of dynCall removal (#12059)
This change now passes flags to binaryen to limit the creation of the dynCall functions and removes more internal use of the legacy dynCall functions. See #12002
1 parent 4ae9f49 commit 953aded

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+250
-309
lines changed

emcc.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,12 @@ def check(input_file):
12671267
if shared.Settings.RELOCATABLE:
12681268
shared.Settings.ALLOW_TABLE_GROWTH = 1
12691269

1270+
if shared.Settings.ASYNCIFY:
1271+
# See: https://github.com/emscripten-core/emscripten/issues/12065
1272+
# See: https://github.com/emscripten-core/emscripten/issues/12066
1273+
shared.Settings.USE_LEGACY_DYNCALLS = 1
1274+
shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$getDynCaller']
1275+
12701276
# Reconfigure the cache now that settings have been applied. Some settings
12711277
# such as LTO and SIDE_MODULE/MAIN_MODULE effect which cache directory we use.
12721278
shared.reconfigure_cache()
@@ -1522,19 +1528,20 @@ def check(input_file):
15221528
'removeRunDependency',
15231529
]
15241530

1525-
if not shared.Settings.MINIMAL_RUNTIME or (shared.Settings.USE_PTHREADS or shared.Settings.EXIT_RUNTIME):
1531+
if not shared.Settings.MINIMAL_RUNTIME or shared.Settings.EXIT_RUNTIME:
15261532
# MINIMAL_RUNTIME only needs callRuntimeCallbacks in certain cases, but the normal runtime
15271533
# always does.
1528-
shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$callRuntimeCallbacks']
1534+
shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$callRuntimeCallbacks', '$dynCall']
15291535

15301536
if shared.Settings.USE_PTHREADS:
15311537
# memalign is used to ensure allocated thread stacks are aligned.
15321538
shared.Settings.EXPORTED_FUNCTIONS += ['_memalign', '_malloc']
15331539

1534-
# dynCall_ii is used to call pthread entry points in worker.js (as
1540+
# dynCall is used to call pthread entry points in worker.js (as
15351541
# metadce does not consider worker.js, which is external, we must
1536-
# consider it a user export, i.e., one which can never be removed).
1537-
building.user_requested_exports += ['dynCall_ii']
1542+
# consider it an export, i.e., one which can never be removed).
1543+
shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$dynCall']
1544+
shared.Settings.EXPORTED_FUNCTIONS += ['dynCall']
15381545

15391546
if shared.Settings.MINIMAL_RUNTIME:
15401547
building.user_requested_exports += ['exit']

emscripten.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,13 @@ def finalize_wasm(temp_files, infile, outfile, memfile, DEBUG):
549549
args.append('-g')
550550
if shared.Settings.WASM_BIGINT:
551551
args.append('--bigint')
552+
553+
if not shared.Settings.USE_LEGACY_DYNCALLS:
554+
if shared.Settings.WASM_BIGINT:
555+
args.append('--no-dyncalls')
556+
else:
557+
args.append('--dyncalls-i64')
558+
552559
if shared.Settings.LEGALIZE_JS_FFI != 1:
553560
args.append('--no-legalize-javascript-ffi')
554561
if not shared.Settings.MEM_INIT_IN_WASM:

src/Fetch.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -454,28 +454,28 @@ function emscripten_start_fetch(fetch, successcb, errorcb, progresscb, readystat
454454
#if FETCH_DEBUG
455455
console.log('fetch: operation success. e: ' + e);
456456
#endif
457-
if (onsuccess) {{{ makeDynCall('vi') }}}(onsuccess, fetch);
457+
if (onsuccess) {{{ makeDynCall('vi', 'onsuccess') }}}(fetch);
458458
else if (successcb) successcb(fetch);
459459
};
460460

461461
var reportProgress = function(fetch, xhr, e) {
462-
if (onprogress) {{{ makeDynCall('vi') }}}(onprogress, fetch);
462+
if (onprogress) {{{ makeDynCall('vi', 'onprogress') }}}(fetch);
463463
else if (progresscb) progresscb(fetch);
464464
};
465465

466466
var reportError = function(fetch, xhr, e) {
467467
#if FETCH_DEBUG
468468
console.error('fetch: operation failed: ' + e);
469469
#endif
470-
if (onerror) {{{ makeDynCall('vi') }}}(onerror, fetch);
470+
if (onerror) {{{ makeDynCall('vi', 'onerror') }}}(fetch);
471471
else if (errorcb) errorcb(fetch);
472472
};
473473

474474
var reportReadyStateChange = function(fetch, xhr, e) {
475475
#if FETCH_DEBUG
476476
console.log('fetch: ready state change. e: ' + e);
477477
#endif
478-
if (onreadystatechange) {{{ makeDynCall('vi') }}}(onreadystatechange, fetch);
478+
if (onreadystatechange) {{{ makeDynCall('vi', 'onreadystatechange') }}}(fetch);
479479
else if (readystatechangecb) readystatechangecb(fetch);
480480
};
481481

@@ -495,14 +495,14 @@ function emscripten_start_fetch(fetch, successcb, errorcb, progresscb, readystat
495495
#if FETCH_DEBUG
496496
console.log('fetch: IndexedDB store succeeded.');
497497
#endif
498-
if (onsuccess) {{{ makeDynCall('vi') }}}(onsuccess, fetch);
498+
if (onsuccess) {{{ makeDynCall('vi', 'onsuccess') }}}(fetch);
499499
else if (successcb) successcb(fetch);
500500
};
501501
var storeError = function(fetch, xhr, e) {
502502
#if FETCH_DEBUG
503503
console.error('fetch: IndexedDB store failed.');
504504
#endif
505-
if (onsuccess) {{{ makeDynCall('vi') }}}(onsuccess, fetch);
505+
if (onsuccess) {{{ makeDynCall('vi', 'onsuccess') }}}(fetch);
506506
else if (successcb) successcb(fetch);
507507
};
508508
__emscripten_fetch_cache_data(Fetch.dbInstance, fetch, xhr.response, storeSuccess, storeError);

src/embind/embind.js

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,42 +1062,20 @@ var LibraryEmbind = {
10621062
#endif
10631063
},
10641064

1065-
$embind__requireFunction__deps: ['$readLatin1String', '$throwBindingError'],
1065+
$embind__requireFunction__deps: ['$readLatin1String', '$throwBindingError', '$getDynCaller'],
10661066
$embind__requireFunction: function(signature, rawFunction) {
10671067
signature = readLatin1String(signature);
10681068

1069-
function makeDynCaller(dynCall) {
1070-
#if DYNAMIC_EXECUTION == 0
1071-
var argCache = [rawFunction];
1072-
return function() {
1073-
argCache.length = arguments.length + 1;
1074-
for (var i = 0; i < arguments.length; i++) {
1075-
argCache[i + 1] = arguments[i];
1076-
}
1077-
return dynCall.apply(null, argCache);
1078-
};
1079-
#else
1080-
var args = [];
1081-
for (var i = 1; i < signature.length; ++i) {
1082-
args.push('a' + i);
1083-
}
1084-
1085-
var name = 'dynCall_' + signature + '_' + rawFunction;
1086-
var body = 'return function ' + name + '(' + args.join(', ') + ') {\n';
1087-
body += ' return dynCall(rawFunction' + (args.length ? ', ' : '') + args.join(', ') + ');\n';
1088-
body += '};\n';
1089-
1090-
return (new Function('dynCall', 'rawFunction', body))(dynCall, rawFunction);
1069+
function makeDynCaller() {
1070+
#if !USE_LEGACY_DYNCALLS
1071+
if (signature.indexOf('j') == -1) {
1072+
return wasmTable.get(rawFunction);
1073+
}
10911074
#endif
1075+
return getDynCaller(signature, rawFunction);
10921076
}
10931077

1094-
#if MINIMAL_RUNTIME
1095-
var dc = asm['dynCall_' + signature];
1096-
#else
1097-
var dc = Module['dynCall_' + signature];
1098-
#endif
1099-
var fp = makeDynCaller(dc);
1100-
1078+
var fp = makeDynCaller();
11011079
if (typeof fp !== "function") {
11021080
throwBindingError("unknown function pointer with signature " + signature + ": " + rawFunction);
11031081
}

src/library.js

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3872,7 +3872,7 @@ LibraryManager.library = {
38723872
var trace = _emscripten_get_callstack_js();
38733873
var parts = trace.split('\n');
38743874
for (var i = 0; i < parts.length; i++) {
3875-
var ret = {{{ makeDynCall('iii') }}}(func, 0, arg);
3875+
var ret = {{{ makeDynCall('iii', 'func') }}}(0, arg);
38763876
if (ret !== 0) return;
38773877
}
38783878
},
@@ -3921,7 +3921,7 @@ LibraryManager.library = {
39213921
emscripten_scan_stack: function(func) {
39223922
var base = STACK_BASE; // TODO verify this is right on pthreads
39233923
var end = stackSave();
3924-
{{{ makeDynCall('vii') }}}(func, Math.min(base, end), Math.max(base, end));
3924+
{{{ makeDynCall('vii', 'func') }}}(Math.min(base, end), Math.max(base, end));
39253925
},
39263926

39273927
// misc definitions to avoid unnecessary unresolved symbols being reported
@@ -4004,6 +4004,60 @@ LibraryManager.library = {
40044004
});
40054005
},
40064006

4007+
#if USE_LEGACY_DYNCALLS || !WASM_BIGINT
4008+
$dynCallLegacy: function(sig, ptr, args) {
4009+
#if ASSERTIONS
4010+
assert(('dynCall_' + sig) in Module, 'bad function pointer type - no table for sig \'' + sig + '\'');
4011+
if (args && args.length) {
4012+
// j (64-bit integer) must be passed in as two numbers [low 32, high 32].
4013+
assert(args.length === sig.substring(1).replace(/j/g, '--').length);
4014+
} else {
4015+
assert(sig.length == 1);
4016+
}
4017+
#endif
4018+
if (args && args.length) {
4019+
return Module['dynCall_' + sig].apply(null, [ptr].concat(args));
4020+
}
4021+
return Module['dynCall_' + sig].call(null, ptr);
4022+
},
4023+
$dynCall__deps: ['$dynCallLegacy'],
4024+
4025+
// Used in library code to get JS function from wasm function pointer.
4026+
// All callers should use direct table access where possible and only fall
4027+
// back to this function if needed.
4028+
$getDynCaller__deps: ['$dynCall'],
4029+
$getDynCaller: function(sig, ptr) {
4030+
#if !USE_LEGACY_DYNCALLS
4031+
assert(sig.indexOf('j') >= 0, 'getDynCaller should only be called with i64 sigs')
4032+
#endif
4033+
var argCache = [];
4034+
return function() {
4035+
argCache.length = arguments.length;
4036+
for (var i = 0; i < arguments.length; i++) {
4037+
argCache[i] = arguments[i];
4038+
}
4039+
return dynCall(sig, ptr, argCache);
4040+
};
4041+
},
4042+
#endif
4043+
4044+
$dynCall: function (sig, ptr, args) {
4045+
#if USE_LEGACY_DYNCALLS
4046+
return dynCallLegacy(sig, ptr, args);
4047+
#else
4048+
#if !WASM_BIGINT
4049+
// Without WASM_BIGINT support we cannot directly call function with i64 as
4050+
// part of thier signature, so we rely the dynCall functions generated by
4051+
// wasm-emscripten-finalize
4052+
if (sig.indexOf('j') != -1) {
4053+
return dynCallLegacy(sig, ptr, args);
4054+
}
4055+
#endif
4056+
4057+
return wasmTable.get(ptr).apply(null, args)
4058+
#endif
4059+
},
4060+
40074061
$callRuntimeCallbacks: function(callbacks) {
40084062
while(callbacks.length > 0) {
40094063
var callback = callbacks.shift();
@@ -4014,9 +4068,9 @@ LibraryManager.library = {
40144068
var func = callback.func;
40154069
if (typeof func === 'number') {
40164070
if (callback.arg === undefined) {
4017-
dynCall_v(func);
4071+
{{{ makeDynCall('v', 'func') }}}();
40184072
} else {
4019-
dynCall_vi(func, callback.arg);
4073+
{{{ makeDynCall('vi', 'func') }}}(callback.arg);
40204074
}
40214075
} else {
40224076
func(callback.arg === undefined ? null : callback.arg);

src/library_async.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ mergeInto(LibraryManager.library, {
340340
Asyncify.afterUnwind = function() {
341341
var stackBegin = Asyncify.currData + {{{ C_STRUCTS.asyncify_data_s.__size__ }}};
342342
var stackEnd = HEAP32[Asyncify.currData >> 2];
343-
{{{ makeDynCall('vii') }}}(func, stackBegin, stackEnd);
343+
{{{ makeDynCall('vii', 'func') }}}(stackBegin, stackEnd);
344344
wakeUp();
345345
};
346346
});
@@ -401,7 +401,7 @@ mergeInto(LibraryManager.library, {
401401
{{{ makeSetValue('newFiber', C_STRUCTS.emscripten_fiber_s.entry, 0, 'i32') }}};
402402

403403
var userData = {{{ makeGetValue('newFiber', C_STRUCTS.emscripten_fiber_s.user_data, 'i32') }}};
404-
{{{ makeDynCall('vi') }}}(entryPoint, userData);
404+
{{{ makeDynCall('vi', 'entryPoint') }}}(userData);
405405
} else {
406406
var asyncifyData = newFiber + {{{ C_STRUCTS.emscripten_fiber_s.asyncify_data }}};
407407
Asyncify.currData = asyncifyData;

0 commit comments

Comments
 (0)