Skip to content

Commit 3e23711

Browse files
authored
Add support for generating optimized JS library function aliases that allow Closure to inline the alias functions away altogether. Optimizes -47 bytes (-0.83%) in minimal WebGL demo. (#7978)
1 parent 95f22e8 commit 3e23711

File tree

6 files changed

+68
-1
lines changed

6 files changed

+68
-1
lines changed

src/library.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1769,16 +1769,19 @@ LibraryManager.library = {
17691769
llvm_exp2_f32: function(x) {
17701770
return Math.pow(2, x);
17711771
},
1772+
llvm_exp2_f64__sig: 'dd',
17721773
llvm_exp2_f64: 'llvm_exp2_f32',
17731774

17741775
llvm_log2_f32: function(x) {
17751776
return Math.log(x) / Math.LN2; // TODO: Math.log2, when browser support is there
17761777
},
1778+
llvm_log2_f64__sig: 'dd',
17771779
llvm_log2_f64: 'llvm_log2_f32',
17781780

17791781
llvm_log10_f32: function(x) {
17801782
return Math.log(x) / Math.LN10; // TODO: Math.log10, when browser support is there
17811783
},
1784+
llvm_log10_f64__sig: 'dd',
17821785
llvm_log10_f64: 'llvm_log10_f32',
17831786

17841787
llvm_copysign_f32: function(x, y) {
@@ -2994,6 +2997,7 @@ LibraryManager.library = {
29942997
{{{ makeSetValue('tp', C_STRUCTS.timespec.tv_nsec, '((now % 1000)*1000*1000)|0', 'i32') }}}; // nanoseconds
29952998
return 0;
29962999
},
3000+
__clock_gettime__sig: 'iii',
29973001
__clock_gettime: 'clock_gettime', // musl internal alias
29983002
clock_settime__deps: ['__setErrNo'],
29993003
clock_settime: function(clk_id, tp) {

src/library_html5.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2129,8 +2129,13 @@ var LibraryJSEvents = {
21292129
_emscripten_webgl_power_preferences: "['default', 'low-power', 'high-performance']",
21302130

21312131
#if !USE_PTHREADS
2132+
emscripten_webgl_create_context__sig: 'iii',
21322133
emscripten_webgl_create_context: 'emscripten_webgl_do_create_context',
2134+
2135+
emscripten_webgl_get_current_context__sig: 'i',
21332136
emscripten_webgl_get_current_context: 'emscripten_webgl_do_get_current_context',
2137+
2138+
emscripten_webgl_commit_frame__sig: 'i',
21342139
emscripten_webgl_commit_frame: 'emscripten_webgl_do_commit_frame',
21352140
#endif
21362141

@@ -2306,6 +2311,7 @@ var LibraryJSEvents = {
23062311
else _emscripten_webgl_get_drawing_buffer_size_main_thread(contextHandle, width, height);
23072312
},
23082313
#else
2314+
emscripten_webgl_get_drawing_buffer_size__sig: 'iiii',
23092315
emscripten_webgl_get_drawing_buffer_size: 'emscripten_webgl_get_drawing_buffer_size_calling_thread',
23102316
#endif
23112317

@@ -2392,6 +2398,7 @@ var LibraryJSEvents = {
23922398
return GL.contexts[contextHandle] ? _emscripten_webgl_destroy_context_calling_thread(contextHandle) : _emscripten_webgl_destroy_context_main_thread(contextHandle);
23932399
},
23942400
#else
2401+
emscripten_webgl_destroy_context__sig: 'vi',
23952402
emscripten_webgl_destroy_context: 'emscripten_webgl_destroy_context_calling_thread',
23962403
#endif
23972404

@@ -2422,6 +2429,7 @@ var LibraryJSEvents = {
24222429
return GL.contexts[contextHandle] ? _emscripten_webgl_enable_extension_calling_thread(contextHandle, extension) : _emscripten_webgl_enable_extension_main_thread(contextHandle, extension);
24232430
},
24242431
#else
2432+
emscripten_webgl_enable_extension__sig: 'iii',
24252433
emscripten_webgl_enable_extension: 'emscripten_webgl_enable_extension_calling_thread',
24262434
#endif
24272435

src/library_pthread_stub.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,10 @@ var LibraryPThreadStub = {
169169
_pthread_cleanup_push.level = __ATEXIT__.length;
170170
},
171171

172+
_pthread_cleanup_push__sig: 'vii',
172173
_pthread_cleanup_push: 'pthread_cleanup_push',
174+
175+
_pthread_cleanup_pop__sig: 'v',
173176
_pthread_cleanup_pop: 'pthread_cleanup_pop',
174177

175178
pthread_sigmask: function() { return 0; },
@@ -343,15 +346,34 @@ var LibraryPThreadStub = {
343346
{{{ makeStructuralReturn(['l', 'h']) }}};
344347
},
345348

349+
emscripten_atomic_add_u32__sig: 'iii',
346350
emscripten_atomic_add_u32: 'llvm_atomic_load_add_i32_p0i32',
351+
352+
emscripten_atomic_load_u64__sig: 'iii',
347353
emscripten_atomic_load_u64: '__atomic_load_8',
354+
355+
emscripten_atomic_store_u64__sig: 'viiii',
348356
emscripten_atomic_store_u64: '__atomic_store_8',
357+
358+
emscripten_atomic_cas_u64__sig: 'iiiiiiii',
349359
emscripten_atomic_cas_u64: '__atomic_compare_exchange_8',
360+
361+
emscripten_atomic_exchange_u64__sig: 'iiiii',
350362
emscripten_atomic_exchange_u64: '__atomic_exchange_8',
363+
364+
_emscripten_atomic_fetch_and_add_u64__sig: 'iiiii',
351365
_emscripten_atomic_fetch_and_add_u64: '__atomic_fetch_add_8',
366+
367+
_emscripten_atomic_fetch_and_sub_u64__sig: 'iiiii',
352368
_emscripten_atomic_fetch_and_sub_u64: '__atomic_fetch_sub_8',
369+
370+
_emscripten_atomic_fetch_and_and_u64__sig: 'iiiii',
353371
_emscripten_atomic_fetch_and_and_u64: '__atomic_fetch_and_8',
372+
373+
_emscripten_atomic_fetch_and_or_u64__sig: 'iiiii',
354374
_emscripten_atomic_fetch_and_or_u64: '__atomic_fetch_or_8',
375+
376+
_emscripten_atomic_fetch_and_xor_u64__sig: 'iiiii',
355377
_emscripten_atomic_fetch_and_xor_u64: '__atomic_fetch_xor_8',
356378

357379
__wait: function() {},

src/library_signals.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ var funs = {
140140
_longjmp(env, value);
141141
},
142142
#else
143+
siglongjmp__sig: 'vii',
143144
siglongjmp: 'longjmp',
144145
#endif
145146
sigpending: function(set) {

src/library_syscall.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,8 +861,11 @@ var SyscallsLibrary = {
861861
var stream = SYSCALLS.getStreamFromFD();
862862
return 0; // we can't do anything synchronously; the in-memory FS is already synced to
863863
},
864+
__syscall150__sig: 'iii',
864865
__syscall150: '__syscall153', // mlock
866+
__syscall151__sig: 'iii',
865867
__syscall151: '__syscall153', // munlock
868+
__syscall152__sig: 'iii',
866869
__syscall152: '__syscall153', // mlockall
867870
__syscall153: function(which, varargs) { // munlockall
868871
return 0;
@@ -972,8 +975,11 @@ var SyscallsLibrary = {
972975
FS.chown(path, owner, group); // XXX we ignore the 'l' aspect, and do the same as chown
973976
return 0;
974977
},
978+
__syscall199__sig: 'iii',
975979
__syscall199: '__syscall202', // getuid32
980+
__syscall200__sig: 'iii',
976981
__syscall200: '__syscall202', // getgid32
982+
__syscall201__sig: 'iii',
977983
__syscall201: '__syscall202', // geteuid32
978984
__syscall202: function(which, varargs) { // getgid32
979985
return 0;
@@ -988,8 +994,11 @@ var SyscallsLibrary = {
988994
FS.chown(path, owner, group);
989995
return 0;
990996
},
997+
__syscall203__sig: 'iii',
991998
__syscall203: '__syscall214', // setreuid32
999+
__syscall204__sig: 'iii',
9921000
__syscall204: '__syscall214', // setregid32
1001+
__syscall213__sig: 'iii',
9931002
__syscall213: '__syscall214', // setuid32
9941003
__syscall214: function(which, varargs) { // setgid32
9951004
var uid = SYSCALLS.get();
@@ -1002,12 +1011,14 @@ var SyscallsLibrary = {
10021011
{{{ makeSetValue('list', '0', '0', 'i32') }}};
10031012
return 1;
10041013
},
1014+
__syscall208__sig: 'iii',
10051015
__syscall208: '__syscall210', // setresuid32
10061016
__syscall210: function(which, varargs) { // setresgid32
10071017
var ruid = SYSCALLS.get(), euid = SYSCALLS.get(), suid = SYSCALLS.get();
10081018
if (euid !== 0) return -ERRNO_CODES.EPERM;
10091019
return 0;
10101020
},
1021+
__syscall209__sig: 'iii',
10111022
__syscall209: '__syscall211', // getresuid
10121023
__syscall211: function(which, varargs) { // getresgid32
10131024
#if SYSCALL_DEBUG

src/modules.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ var Types = {
3131

3232
var firstTableIndex = RESERVED_FUNCTION_POINTERS + 1;
3333

34+
// Constructs an array ['a0', 'a1', 'a2', ..., 'a(n-1)']
35+
function genArgSequence(n) {
36+
var args = [];
37+
for(var i = 0; i < n; ++i) {
38+
args.push('a'+i);
39+
}
40+
return args;
41+
}
42+
3443
var Functions = {
3544
// All functions that will be implemented in this file. Maps id to signature
3645
implementedFunctions: {},
@@ -220,7 +229,19 @@ var LibraryManager = {
220229
if (lib[target + '__asm']) continue; // This is an alias of an asm library function. Also needs to be fully optimized.
221230
if (!isNaN(target)) continue; // This is a number, and so cannot be an alias target.
222231
if (typeof lib[target] === 'undefined' || typeof lib[target] === 'function') {
223-
lib[x] = new Function('return _' + target + '.apply(null, arguments)');
232+
// If the alias provides a signature, then construct a specific 'function foo(a0, a1, a2) { [return] _target(a0, a1, a2); }' form of forwarding.
233+
// Otherwise construct a generic 'function foo() { return _target.apply(null, arguments); }' forwarding.
234+
// The benefit of the first form is that Closure is able to fully inline and reason about the function.
235+
// Note that the signature is checked on the alias function, not on the target function. That allows aliases to choose individually which form
236+
// to use.
237+
if (lib[x + '__sig']) {
238+
var argCount = lib[x + '__sig'].length - 1;
239+
var ret = lib[x + '__sig'] == 'v' ? '' : 'return ';
240+
var args = genArgSequence(argCount).join(',');
241+
lib[x] = new Function(args, ret + '_' + target + '(' + args + ');');
242+
} else {
243+
lib[x] = new Function('return _' + target + '.apply(null, arguments)');
244+
}
224245
if (!lib[x + '__deps']) lib[x + '__deps'] = [];
225246
lib[x + '__deps'].push(target);
226247
}

0 commit comments

Comments
 (0)