Skip to content

Commit aa5170b

Browse files
committed
Revise the API.
1 parent 3563c51 commit aa5170b

File tree

7 files changed

+323
-254
lines changed

7 files changed

+323
-254
lines changed

emcc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1283,7 +1283,7 @@ def default_setting(name, new_default):
12831283
exit_with_error('Invalid option -s CLOSURE_WARNINGS=%s specified! Allowed values are "quiet", "warn" or "error".' % shared.Settings.CLOSURE_WARNINGS)
12841284

12851285
# Calling function pointers from JS libraries is default runtime functionality, so always include the functionality. (to be DCEd if not used)
1286-
shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$dynCall', '$bindDynCall', '$bindDynCallArray']
1286+
shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$dynCall']
12871287

12881288
if shared.Settings.MAIN_MODULE:
12891289
assert not shared.Settings.SIDE_MODULE

emscripten.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ def make_wasm_table_static_dyncaller(func):
4949
i += 1
5050
ptr_args = ('ptr, ' + args) if len(args) > 0 else 'ptr'
5151

52-
return 'function ' + func + '(' + ptr_args + ') { ' + ret + 'wasmTable.get(ptr)(' + args + '); }'
52+
dyncall = ('dyncalls["' + sig + '"]') if shared.Settings.MINIMAL_RUNTIME else ('Module["' + func + '"]')
53+
wasmTableGet = 'wasmTableGet' if shared.Settings.SHRINK_LEVEL == 0 else 'wasmTable.get'
54+
return 'function ' + func + '(' + ptr_args + ') { ' + ret + dyncall + '(' + ptr_args + '); }\n'
5355

5456

5557
def compute_minimal_runtime_initializer_and_exports(post, exports, receiving):
@@ -62,7 +64,7 @@ def compute_minimal_runtime_initializer_and_exports(post, exports, receiving):
6264

6365
static_dyncall_sig_functions = ''
6466

65-
if shared.Settings.USE_LEGACY_DYNCALLS:
67+
if shared.Settings.USE_LEGACY_DYNCALLS or not shared.Settings.WASM_BIGINT:
6668
if len([x for x in exports_that_are_not_initializers if x.startswith('dynCall_')]) > 0:
6769
exports_that_are_not_initializers += ['dynCalls = {}']
6870
else:
@@ -726,7 +728,7 @@ def create_receiving(exports):
726728
return ''
727729

728730
exports_that_are_not_initializers = [x for x in exports if x != WASM_INIT_FUNC]
729-
if not shared.Settings.USE_LEGACY_DYNCALLS:
731+
if not shared.Settings.USE_LEGACY_DYNCALLS and shared.Settings.WASM_BIGINT:
730732
exports_that_are_not_initializers = [x for x in exports_that_are_not_initializers if not x.startswith('dynCall_')]
731733

732734
receiving = []
@@ -743,7 +745,7 @@ def create_receiving(exports):
743745
# _main = asm["_main"];
744746
for s in exports_that_are_not_initializers:
745747
mangled = asmjs_mangle(s)
746-
dynCallAssignment = ('dynCalls["' + s.replace('dynCall_', '') + '"] = ') if shared.Settings.USE_LEGACY_DYNCALLS and mangled.startswith('dynCall_') else ''
748+
dynCallAssignment = ('dynCalls["' + s.replace('dynCall_', '') + '"] = ') if shared.Settings.USE_LEGACY_DYNCALLS or not shared.Settings.WASM_BIGINT and mangled.startswith('dynCall_') else ''
747749
receiving += [dynCallAssignment + mangled + ' = asm["' + s + '"];']
748750
else:
749751
if shared.Settings.MINIMAL_RUNTIME:

src/library_dyncall.js

Lines changed: 54 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,67 @@
11
mergeInto(LibraryManager.library, {
2-
$bindDynCall: function(funcPtr) {
2+
{{{ (function() { global.wbind = function() { return SHRINK_LEVEL == 0 ? 'wbind' : 'wasmTable.get'; }; return null; })(); }}}
3+
{{{ (function() { global.getDynCaller = function(sig) { return MINIMAL_RUNTIME ? `dynCalls[${sig}]` : `Module["dynCall_${sig}]`; }; return null; })(); }}}
4+
5+
#if SHRINK_LEVEL == 0
6+
// A mirror copy of contents of wasmTable in JS side, to avoid relatively
7+
// slow wasmTable.get() call. Only used when not compiling with -Os or -Oz.
8+
_wasmTableMirror: [],
9+
10+
$wbind__deps: ['_wasmTableMirror'],
11+
$wbind: function(funcPtr) {
12+
var func = __wasmTableMirror[funcPtr];
13+
if (!func) {
14+
if (funcPtr >= __wasmTableMirror.length) __wasmTableMirror.length = funcPtr + 1;
15+
__wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
16+
}
17+
return func;
18+
},
19+
20+
$dynCall__deps: ['$wbind'],
21+
$bindDynCall__deps: ['$wbind'],
22+
$wbindArray__deps: ['$wbind'],
23+
#else
24+
$wbind: function(funcPtr) {
25+
// In -Os and -Oz builds, do not implement a JS side wasm table mirror for small
26+
// code size, but directly access wasmTable, which is a bit slower.
327
return wasmTable.get(funcPtr);
428
},
29+
#endif
530

6-
$bindDynCallArray: function(funcPtr) {
7-
var func = wasmTable.get(funcPtr);
8-
return func.length ? function(args) {
9-
return func.apply(null, args);
10-
} : function() { return func(); }
31+
// A helper that binds a wasm function into a form that can be called by passing all
32+
// the parameters in an array, e.g. wbindArray(func)([param1, param2, ..., paramN]).
33+
$wbindArray: function(funcPtr) {
34+
var func = {{{wbind()}}}(funcPtr);
35+
return func.length
36+
? function(args) { return func.apply(null, args); }
37+
: function() { return func(); }
1138
},
1239

13-
#if USE_LEGACY_DYNCALLS || !WASM_BIGINT
14-
$dynCallLegacy: function(sig, ptr, args) {
15-
#if ASSERTIONS
16-
assert(('dynCall_' + sig) in Module, 'bad function pointer type - no table for sig \'' + sig + '\'');
17-
if (args && args.length) {
18-
// j (64-bit integer) must be passed in as two numbers [low 32, high 32].
19-
assert(args.length === sig.substring(1).replace(/j/g, '--').length);
20-
} else {
21-
assert(sig.length == 1);
22-
}
23-
#endif
24-
if (args && args.length) {
25-
return Module['dynCall_' + sig].apply(null, [ptr].concat(args));
26-
}
27-
return Module['dynCall_' + sig].call(null, ptr);
40+
// A helper that returns a function that can be used to invoke function pointers, i.e.
41+
// getDynCaller('vi')(funcPtr, myInt);
42+
$getDynCaller: function(sig, funcPtr) {
43+
return {{{getDynCaller('sig')}}};
2844
},
2945

30-
// Used in library code to get JS function from wasm function pointer.
31-
// All callers should use direct table access where possible and only fall
32-
// back to this function if needed.
33-
$getDynCaller__deps: ['$dynCall'],
34-
$getDynCaller: function(sig, ptr) {
35-
#if !USE_LEGACY_DYNCALLS
36-
assert(sig.indexOf('j') >= 0, 'getDynCaller should only be called with i64 sigs')
37-
#endif
38-
var argCache = [];
39-
return function() {
40-
argCache.length = arguments.length;
41-
for (var i = 0; i < arguments.length; i++) {
42-
argCache[i] = arguments[i];
43-
}
44-
return dynCall(sig, ptr, argCache);
45-
};
46+
$bindDynCall: function(sig, funcPtr) {
47+
// For int64 signatures, use the dynCall_sig dispatch mechanism.
48+
if (sig.includes('j')) return function(args) {
49+
return {{{getDynCaller('sig')}}}.apply(null, [funcPtr].concat(args));
50+
}
51+
// For non-int64 signatures, invoke via the wasm table.
52+
var func = {{{wbind()}}}(funcPtr);
53+
return func.length
54+
? function(args) { return func.apply(null, args); }
55+
: function() { return func(); }
4656
},
47-
#endif
4857

49-
// $dynCall__deps: ['$dynCallLegacy'],
50-
$dynCall: function(sig, ptr, args) {
51-
#if USE_LEGACY_DYNCALLS
52-
#if MINIMAL_RUNTIME
53-
var func = dynCalls[sig];
54-
#else
55-
var func = Module['dynCall_'+sig];
56-
#endif
57-
return args ? func.apply(null, [ptr].concat(args)) : func(ptr);
58-
#else
59-
#if !WASM_BIGINT
60-
// Without WASM_BIGINT support we cannot directly call function with i64 as
61-
// part of thier signature, so we rely the dynCall functions generated by
62-
// wasm-emscripten-finalize
63-
if (sig.indexOf('j') != -1) {
64-
#if MINIMAL_RUNTIME
65-
var func = dynCalls[sig];
66-
#else
67-
var func = Module['dynCall_'+sig];
68-
#endif
69-
return args ? func.apply(null, [ptr].concat(args)) : func(ptr);
58+
$dynCall: function(sig, funcPtr, args) {
59+
// For int64 signatures, use the dynCall_sig dispatch mechanism.
60+
if (sig.includes('j')) {
61+
return {{{getDynCaller('sig')}}}.apply(null, [funcPtr].concat(args));
7062
}
71-
#endif
72-
#if ASSERTIONS
73-
assert(wasmTable.get(ptr), 'missing table entry in dynCall: ' + ptr);
74-
#endif
75-
return wasmTable.get(ptr).apply(null, args)
76-
#endif
63+
64+
// For non-int64 signatures, invoke via the wasm table.
65+
return {{{wbind()}}}(funcPtr).apply(null, args);
7766
}
7867
});

0 commit comments

Comments
 (0)