Skip to content

Commit ca0add6

Browse files
committed
Micro-optimize performance and code size generated for longjmp in Emscripten invokes to avoid string comparisons
1 parent 164346a commit ca0add6

File tree

4 files changed

+13
-11
lines changed

4 files changed

+13
-11
lines changed

src/library.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1409,7 +1409,7 @@ LibraryManager.library = {
14091409
// ==========================================================================
14101410

14111411
_emscripten_throw_longjmp__sig: 'v',
1412-
_emscripten_throw_longjmp: function() { throw 'longjmp'; },
1412+
_emscripten_throw_longjmp: function() { throw Infinity; },
14131413
#if !SUPPORT_LONGJMP
14141414
#if !INCLUDE_FULL_LIBRARY
14151415
// These are in order to print helpful error messages when either longjmp of

src/library_dylink.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,10 @@ var LibraryDylink = {
235235
return dynCall(sig, arguments[0], Array.prototype.slice.call(arguments, 1));
236236
} catch(e) {
237237
stackRestore(sp);
238-
if (e !== e+0 && e !== 'longjmp') throw e;
238+
// Exceptions thrown from C++ exception will be integer numbers.
239+
// longjmp will throw the number Infinity. Re-throw other types of
240+
// exceptions using a compact and fast check.
241+
if (e !== e+0) throw e;
239242
_setThrew(1, 0);
240243
}
241244
}

src/preamble.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@ function makeAbortWrapper(original) {
707707
ABORT // rethrow exception if abort() was called in the original function call above
708708
|| abortWrapperDepth > 1 // rethrow exceptions not caught at the top level if exception catching is enabled; rethrow from exceptions from within callMain
709709
#if SUPPORT_LONGJMP == 'emscripten'
710-
|| e === 'longjmp' // rethrow longjmp if enabled
710+
|| e === Infinity // rethrow longjmp if enabled (In Emscripten EH format longjmp will throw Infinity)
711711
#endif
712712
) {
713713
throw e;

tools/shared.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -687,12 +687,11 @@ def make_invoke(sig, named=True):
687687
args = ['index'] + ['a' + str(i) for i in range(1, len(legal_sig))]
688688
ret = 'return ' if sig[0] != 'v' else ''
689689
body = '%s%s;' % (ret, JS.make_dynCall(sig, args))
690-
# C++ exceptions are numbers, and longjmp is a string 'longjmp'
691-
if settings.SUPPORT_LONGJMP:
692-
rethrow = "if (e !== e+0 && e !== 'longjmp') throw e;"
693-
else:
694-
rethrow = "if (e !== e+0) throw e;"
695-
690+
# Exceptions thrown from C++ exception will be integer numbers.
691+
# longjmp will throw the number Infinity.
692+
# Create a try-catch guard that rethrows the exception if anything else
693+
# than a Number was thrown. To do that quickly and in a code size conserving
694+
# manner, use the compact test "e !== e+0" to check if e was not a Number.
696695
name = (' invoke_' + sig) if named else ''
697696
ret = '''\
698697
function%s(%s) {
@@ -701,10 +700,10 @@ def make_invoke(sig, named=True):
701700
%s
702701
} catch(e) {
703702
stackRestore(sp);
704-
%s
703+
if (e !== e+0) throw e;
705704
_setThrew(1, 0);
706705
}
707-
}''' % (name, ','.join(args), body, rethrow)
706+
}''' % (name, ','.join(args), body)
708707

709708
return ret
710709

0 commit comments

Comments
 (0)