Skip to content

Commit 6880b20

Browse files
committed
Part two of dynCall removal
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 fa91e13 commit 6880b20

37 files changed

+197
-233
lines changed

emcc.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,10 @@ def check(input_file):
12601260
if shared.Settings.RELOCATABLE:
12611261
shared.Settings.ALLOW_TABLE_GROWTH = 1
12621262

1263+
if shared.Settings.WASM2C or shared.Settings.ASYNCIFY or shared.Settings.EMBIND:
1264+
shared.Settings.USE_LEGACY_DYNCALLS = 1
1265+
shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$getDynCallerBound']
1266+
12631267
# Reconfigure the cache now that settings have been applied. Some settings
12641268
# such as LTO and SIDE_MODULE/MAIN_MODULE effect which cache directory we use.
12651269
shared.reconfigure_cache()
@@ -1515,7 +1519,7 @@ def check(input_file):
15151519
'removeRunDependency',
15161520
]
15171521

1518-
if not shared.Settings.MINIMAL_RUNTIME or (shared.Settings.USE_PTHREADS or shared.Settings.EXIT_RUNTIME):
1522+
if not shared.Settings.MINIMAL_RUNTIME or shared.Settings.EXIT_RUNTIME:
15191523
# MINIMAL_RUNTIME only needs callRuntimeCallbacks in certain cases, but the normal runtime
15201524
# always does.
15211525
shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$callRuntimeCallbacks']
@@ -1524,10 +1528,7 @@ def check(input_file):
15241528
# memalign is used to ensure allocated thread stacks are aligned.
15251529
shared.Settings.EXPORTED_FUNCTIONS += ['_memalign', '_malloc']
15261530

1527-
# dynCall_ii is used to call pthread entry points in worker.js (as
1528-
# metadce does not consider worker.js, which is external, we must
1529-
# consider it a user export, i.e., one which can never be removed).
1530-
building.user_requested_exports += ['dynCall_ii']
1531+
shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$dynCall']
15311532

15321533
if shared.Settings.MINIMAL_RUNTIME:
15331534
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/library.js

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3867,12 +3867,12 @@ LibraryManager.library = {
38673867

38683868
// libunwind
38693869

3870-
_Unwind_Backtrace__deps: ['emscripten_get_callstack_js'],
3870+
_Unwind_Backtrace__deps: ['emscripten_get_callstack_js', '$getDynCaller'],
38713871
_Unwind_Backtrace: function(func, arg) {
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 = {{{ makeDynCallBound('iii', 'func') }}}(0, arg);
38763876
if (ret !== 0) return;
38773877
}
38783878
},
@@ -3918,10 +3918,11 @@ LibraryManager.library = {
39183918

39193919
// special runtime support
39203920

3921+
emscripten_scan_stack__deps: ['$getDynCaller'],
39213922
emscripten_scan_stack: function(func) {
39223923
var base = STACK_BASE; // TODO verify this is right on pthreads
39233924
var end = stackSave();
3924-
{{{ makeDynCall('vii') }}}(func, Math.min(base, end), Math.max(base, end));
3925+
{{{ makeDynCallBound('vii', 'func') }}}(Math.min(base, end), Math.max(base, end));
39253926
},
39263927

39273928
// misc definitions to avoid unnecessary unresolved symbols being reported
@@ -4004,6 +4005,57 @@ LibraryManager.library = {
40044005
});
40054006
},
40064007

4008+
#if USE_LEGACY_DYNCALLS || !WASM_BIGINT
4009+
$dynCallLegacy: function(sig, ptr, args) {
4010+
#if ASSERTIONS
4011+
assert(('dynCall_' + sig) in Module, 'bad function pointer type - no table for sig \'' + sig + '\'');
4012+
if (args && args.length) {
4013+
// j (64-bit integer) must be passed in as two numbers [low 32, high 32].
4014+
assert(args.length === sig.substring(1).replace(/j/g, '--').length);
4015+
} else {
4016+
assert(sig.length == 1);
4017+
}
4018+
#endif
4019+
if (args && args.length) {
4020+
return Module['dynCall_' + sig].apply(null, [ptr].concat(args));
4021+
}
4022+
return Module['dynCall_' + sig].call(null, ptr);
4023+
},
4024+
$dynCall__deps: ['$dynCallLegacy'],
4025+
#endif
4026+
4027+
$dynCall: function (sig, ptr, args) {
4028+
#if USE_LEGACY_DYNCALLS
4029+
return dynCallLegacy(sig, ptr, args);
4030+
#else
4031+
#if !WASM_BIGINT
4032+
// Without WASM_BIGINT support we cannot directly call function with i64 as
4033+
// part of thier signature, so we rely the dynCall functions generated by
4034+
// wasm-emscripten-finalize
4035+
if (sig.indexOf('j') != -1) {
4036+
return dynCallLegacy(sig, ptr, args);
4037+
}
4038+
#endif
4039+
4040+
return wasmTable.get(ptr).apply(null, args)
4041+
#endif
4042+
},
4043+
4044+
$getDynCaller__deps: ['$dynCall'],
4045+
$getDynCaller: function(sig) {
4046+
return function(ptr) {
4047+
return dynCall(sig, ptr, Array.prototype.slice.call(arguments, 1));
4048+
};
4049+
},
4050+
4051+
$getDynCalleBoundr__deps: ['$dynCall'],
4052+
$getDynCallerBound: function(sig, ptr) {
4053+
return function() {
4054+
return dynCall(sig, ptr, Array.prototype.slice.call(arguments));
4055+
};
4056+
},
4057+
4058+
$callRuntimeCallbacks__deps: ['$dynCall'],
40074059
$callRuntimeCallbacks: function(callbacks) {
40084060
while(callbacks.length > 0) {
40094061
var callback = callbacks.shift();
@@ -4014,9 +4066,9 @@ LibraryManager.library = {
40144066
var func = callback.func;
40154067
if (typeof func === 'number') {
40164068
if (callback.arg === undefined) {
4017-
dynCall_v(func);
4069+
{{{ makeDynCallBound('v', 'func') }}}();
40184070
} else {
4019-
dynCall_vi(func, callback.arg);
4071+
{{{ makeDynCallBound('vi', 'func') }}}(callback.arg);
40204072
}
40214073
} else {
40224074
func(callback.arg === undefined ? null : callback.arg);

src/library_async.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ mergeInto(LibraryManager.library, {
340340
});
341341
},
342342

343+
emscripten_scan_registers__deps: ['$getDynCaller'],
343344
emscripten_scan_registers: function(func) {
344345
Asyncify.handleSleep(function(wakeUp) {
345346
// We must first unwind, so things are spilled to the stack. We
@@ -364,7 +365,7 @@ mergeInto(LibraryManager.library, {
364365
});
365366
},
366367

367-
$Fibers__deps: ['$Asyncify'],
368+
$Fibers__deps: ['$Asyncify', '$getDynCaller'],
368369
$Fibers: {
369370
nextFiber: 0,
370371
trampolineRunning: false,

src/library_browser.js

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,7 @@ var LibraryBrowser = {
831831
function doCallback(callback) {
832832
if (callback) {
833833
var stack = stackSave();
834-
{{{ makeDynCall('vi') }}}(callback, allocate(intArrayFromString(_file), 'i8', ALLOC_STACK));
834+
{{{ makeDynCallBound('vi', 'callback') }}}(allocate(intArrayFromString(_file), 'i8', ALLOC_STACK));
835835
stackRestore(stack);
836836
}
837837
}
@@ -861,7 +861,7 @@ var LibraryBrowser = {
861861

862862
$funcWrappers: {},
863863

864-
$getFuncWrapper__deps: ['$funcWrappers'],
864+
$getFuncWrapper__deps: ['$funcWrappers', '$dynCall'],
865865
$getFuncWrapper: function(func, sig) {
866866
if (!func) return; // on null pointer, return undefined
867867
assert(sig);
@@ -895,10 +895,10 @@ var LibraryBrowser = {
895895
Browser.asyncLoad(UTF8ToString(url), function(byteArray) {
896896
var buffer = _malloc(byteArray.length);
897897
HEAPU8.set(byteArray, buffer);
898-
{{{ makeDynCall('viii') }}}(onload, arg, buffer, byteArray.length);
898+
{{{ makeDynCallBound('viii', 'onload') }}}(arg, buffer, byteArray.length);
899899
_free(buffer);
900900
}, function() {
901-
if (onerror) {{{ makeDynCall('vi') }}}(onerror, arg);
901+
if (onerror) {{{ makeDynCallBound('vi', 'onerror') }}}(arg);
902902
}, true /* no need for run dependency, this is async but will not do any prepare etc. step */ );
903903
},
904904

@@ -936,27 +936,27 @@ var LibraryBrowser = {
936936
FS.createDataFile( _file.substr(0, index), _file.substr(index + 1), new Uint8Array(/** @type{ArrayBuffer}*/(http.response)), true, true, false);
937937
if (onload) {
938938
var stack = stackSave();
939-
{{{ makeDynCall('viii') }}}(onload, handle, arg, allocate(intArrayFromString(_file), 'i8', ALLOC_STACK));
939+
{{{ makeDynCallBound('viii', 'onload') }}}(handle, arg, allocate(intArrayFromString(_file), 'i8', ALLOC_STACK));
940940
stackRestore(stack);
941941
}
942942
} else {
943-
if (onerror) {{{ makeDynCall('viii') }}}(onerror, handle, arg, http.status);
943+
if (onerror) {{{ makeDynCallBound('viii', 'onerror') }}}(handle, arg, http.status);
944944
}
945945

946946
delete Browser.wgetRequests[handle];
947947
};
948948

949949
// ERROR
950950
http.onerror = function http_onerror(e) {
951-
if (onerror) {{{ makeDynCall('viii') }}}(onerror, handle, arg, http.status);
951+
if (onerror) {{{ makeDynCallBound('viii', 'onerror') }}}(handle, arg, http.status);
952952
delete Browser.wgetRequests[handle];
953953
};
954954

955955
// PROGRESS
956956
http.onprogress = function http_onprogress(e) {
957957
if (e.lengthComputable || (e.lengthComputable === undefined && e.total != 0)) {
958958
var percentComplete = (e.loaded / e.total)*100;
959-
if (onprogress) {{{ makeDynCall('viii') }}}(onprogress, handle, arg, percentComplete);
959+
if (onprogress) {{{ makeDynCallBound('viii', 'onprogress') }}}(handle, arg, percentComplete);
960960
}
961961
};
962962

@@ -997,25 +997,25 @@ var LibraryBrowser = {
997997
var byteArray = new Uint8Array(/** @type{ArrayBuffer} */(http.response));
998998
var buffer = _malloc(byteArray.length);
999999
HEAPU8.set(byteArray, buffer);
1000-
if (onload) {{{ makeDynCall('viiii') }}}(onload, handle, arg, buffer, byteArray.length);
1000+
if (onload) {{{ makeDynCallBound('viiii', 'onload') }}}(handle, arg, buffer, byteArray.length);
10011001
if (free) _free(buffer);
10021002
} else {
1003-
if (onerror) {{{ makeDynCall('viiii') }}}(onerror, handle, arg, http.status, http.statusText);
1003+
if (onerror) {{{ makeDynCallBound('viiii', 'onerror') }}}(handle, arg, http.status, http.statusText);
10041004
}
10051005
delete Browser.wgetRequests[handle];
10061006
};
10071007

10081008
// ERROR
10091009
http.onerror = function http_onerror(e) {
10101010
if (onerror) {
1011-
{{{ makeDynCall('viiii') }}}(onerror, handle, arg, http.status, http.statusText);
1011+
{{{ makeDynCallBound('viiii', 'onerror') }}}(handle, arg, http.status, http.statusText);
10121012
}
10131013
delete Browser.wgetRequests[handle];
10141014
};
10151015

10161016
// PROGRESS
10171017
http.onprogress = function http_onprogress(e) {
1018-
if (onprogress) {{{ makeDynCall('viiii') }}}(onprogress, handle, arg, e.loaded, e.lengthComputable || e.lengthComputable === undefined ? e.total : 0);
1018+
if (onprogress) {{{ makeDynCallBound('viiii', 'onprogress') }}}(handle, arg, e.loaded, e.lengthComputable || e.lengthComputable === undefined ? e.total : 0);
10191019
};
10201020

10211021
// ABORT
@@ -1059,10 +1059,10 @@ var LibraryBrowser = {
10591059
PATH.basename(_file),
10601060
new Uint8Array(data.object.contents), true, true,
10611061
function() {
1062-
if (onload) {{{ makeDynCall('vi') }}}(onload, file);
1062+
if (onload) {{{ makeDynCallBound('vi', 'onload') }}}(file);
10631063
},
10641064
function() {
1065-
if (onerror) {{{ makeDynCall('vi') }}}(onerror, file);
1065+
if (onerror) {{{ makeDynCallBound('vi', 'onerror') }}}(file);
10661066
},
10671067
true // don'tCreateFile - it's already there
10681068
);
@@ -1086,10 +1086,10 @@ var LibraryBrowser = {
10861086
{{{ makeHEAPView('U8', 'data', 'data + size') }}},
10871087
true, true,
10881088
function() {
1089-
if (onload) {{{ makeDynCall('vii') }}}(onload, arg, cname);
1089+
if (onload) {{{ makeDynCallBound('vii', 'onload') }}}(arg, cname);
10901090
},
10911091
function() {
1092-
if (onerror) {{{ makeDynCall('vi') }}}(onerror, arg);
1092+
if (onerror) {{{ makeDynCallBound('vi', 'onerror') }}}(arg);
10931093
},
10941094
true // don'tCreateFile - it's already there
10951095
);
@@ -1196,10 +1196,10 @@ var LibraryBrowser = {
11961196
return 0;
11971197
},
11981198

1199-
emscripten_set_main_loop__deps: ['$setMainLoop'],
1199+
emscripten_set_main_loop__deps: ['$setMainLoop', '$getDynCaller'],
12001200
emscripten_set_main_loop__docs: '/** @param {number|boolean=} noSetTiming */',
12011201
emscripten_set_main_loop: function(func, fps, simulateInfiniteLoop, arg, noSetTiming) {
1202-
var browserIterationFunc = function() { {{{ makeDynCall('v') }}}(func); };
1202+
var browserIterationFunc = function() { {{{ makeDynCallBound('v', 'func') }}}(); };
12031203
setMainLoop(browserIterationFunc, fps, simulateInfiniteLoop, arg, noSetTiming);
12041204
},
12051205

@@ -1334,7 +1334,7 @@ var LibraryBrowser = {
13341334
// Runs natively in pthread, no __proxy needed.
13351335
emscripten_set_main_loop_arg__deps: ['$setMainLoop'],
13361336
emscripten_set_main_loop_arg: function(func, arg, fps, simulateInfiniteLoop) {
1337-
var browserIterationFunc = function() { {{{ makeDynCall('vi') }}}(func, arg); };
1337+
var browserIterationFunc = function() { {{{ makeDynCallBound('vi', 'func') }}}(arg); };
13381338
setMainLoop(browserIterationFunc, fps, simulateInfiniteLoop, arg);
13391339
},
13401340

@@ -1357,15 +1357,15 @@ var LibraryBrowser = {
13571357
// Runs natively in pthread, no __proxy needed.
13581358
_emscripten_push_main_loop_blocker: function(func, arg, name) {
13591359
Browser.mainLoop.queue.push({ func: function() {
1360-
{{{ makeDynCall('vi') }}}(func, arg);
1360+
{{{ makeDynCallBound('vi', 'func') }}}(arg);
13611361
}, name: UTF8ToString(name), counted: true });
13621362
Browser.mainLoop.updateStatus();
13631363
},
13641364

13651365
// Runs natively in pthread, no __proxy needed.
13661366
_emscripten_push_uncounted_main_loop_blocker: function(func, arg, name) {
13671367
Browser.mainLoop.queue.push({ func: function() {
1368-
{{{ makeDynCall('vi') }}}(func, arg);
1368+
{{{ makeDynCallBound('vi', 'func') }}}(arg);
13691369
}, name: UTF8ToString(name), counted: false });
13701370
Browser.mainLoop.updateStatus();
13711371
},
@@ -1382,7 +1382,7 @@ var LibraryBrowser = {
13821382
noExitRuntime = true;
13831383

13841384
function wrapper() {
1385-
{{{ makeDynCall('vi') }}}(func, arg);
1385+
{{{ makeDynCallBound('vi', 'func') }}}(arg);
13861386
}
13871387

13881388
if (millis >= 0) {

src/library_exceptions.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ var LibraryExceptions = {
179179
info.add_ref();
180180
},
181181

182-
$exception_decRef__deps: ['__cxa_free_exception'
182+
$exception_decRef__deps: ['__cxa_free_exception', '$getDynCaller',
183183
#if EXCEPTION_DEBUG
184184
, '$exceptionLast', '$exceptionCaught'
185185
#endif
@@ -195,7 +195,7 @@ var LibraryExceptions = {
195195
var destructor = info.get_destructor();
196196
if (destructor) {
197197
// In Wasm, destructors return 'this' as in ARM
198-
{{{ makeDynCall('ii') }}}(destructor, info.excPtr);
198+
{{{ makeDynCallBound('ii', 'destructor') }}}(info.excPtr);
199199
}
200200
___cxa_free_exception(info.excPtr);
201201
#if EXCEPTION_DEBUG

0 commit comments

Comments
 (0)