diff options
-rw-r--r-- | src/compiler.js | 1 | ||||
-rw-r--r-- | src/intertyper.js | 2 | ||||
-rw-r--r-- | src/jsifier.js | 23 | ||||
-rw-r--r-- | src/parseTools.js | 2 | ||||
-rw-r--r-- | src/settings.js | 8 | ||||
-rwxr-xr-x | tests/runner.py | 32 |
6 files changed, 59 insertions, 9 deletions
diff --git a/src/compiler.js b/src/compiler.js index 118ca83a..25c306cf 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -168,6 +168,7 @@ if (PGO) { // by default, correct everything during PGO EXPORTED_FUNCTIONS = set(EXPORTED_FUNCTIONS); EXPORTED_GLOBALS = set(EXPORTED_GLOBALS); +EXCEPTION_CATCHING_WHITELIST = set(EXCEPTION_CATCHING_WHITELIST); RUNTIME_DEBUG = LIBRARY_DEBUG || GL_DEBUG; diff --git a/src/intertyper.js b/src/intertyper.js index 00d504f5..1ddf8701 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -725,7 +725,7 @@ function intertyper(data, sidePass, baseLineNums) { substrate.addActor('Invoke', { processItem: function(item) { var result = makeCall.call(this, item, 'invoke'); - if (DISABLE_EXCEPTION_CATCHING) { + if (DISABLE_EXCEPTION_CATCHING == 1) { result.item.intertype = 'call'; result.ret.push({ intertype: 'branch', diff --git a/src/jsifier.js b/src/jsifier.js index 77da7a2c..796b3806 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1172,13 +1172,22 @@ function JSify(data, functionsOnly, givenFunctions) { // in an assignment var phiSets = calcPhiSets(item); var call_ = makeFunctionCall(item.ident, item.params, item.funcData, item.type); - var ret = '(function() { try { __THREW__ = 0; return ' - + call_ + ' ' - + '} catch(e) { ' - + 'if (typeof e != "number") throw e; ' - + 'if (ABORT) throw e; __THREW__ = 1; ' - + (EXCEPTION_DEBUG ? 'Module.print("Exception: " + e + ", currently at: " + (new Error().stack)); ' : '') - + 'return null } })();'; + + var ret; + + if (DISABLE_EXCEPTION_CATCHING == 2 && !(item.funcData.ident in EXCEPTION_CATCHING_WHITELIST)) { + ret = call_ + ';'; + } else { + ret = '(function() { try { __THREW__ = 0; return ' + + call_ + ' ' + + '} catch(e) { ' + + 'if (typeof e != "number") throw e; ' + + 'if (ABORT) throw e; __THREW__ = 1; ' + + (EXCEPTION_DEBUG ? 'Module.print("Exception: " + e + ", currently at: " + (new Error().stack)); ' : '') + + 'return null } })();'; + } + + if (item.assignTo) { ret = 'var ' + item.assignTo + ' = ' + ret; if (USE_TYPED_ARRAYS == 2 && isIllegalType(item.type)) { diff --git a/src/parseTools.js b/src/parseTools.js index 8fded758..b346b8a7 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -1681,7 +1681,7 @@ function makeStructuralAccess(ident, i) { } function makeThrow(what) { - return 'throw ' + what + (DISABLE_EXCEPTION_CATCHING ? ' + " - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 to catch."' : '') + ';'; + return 'throw ' + what + (DISABLE_EXCEPTION_CATCHING == 1 ? ' + " - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch."' : '') + ';'; } // From parseLLVMSegment diff --git a/src/settings.js b/src/settings.js index 8ae287f9..ccf2a25b 100644 --- a/src/settings.js +++ b/src/settings.js @@ -158,8 +158,16 @@ var DISABLE_EXCEPTION_CATCHING = 0; // Disables generating code to actually catc // then this can make it much faster. If an exception actually happens, // it will not be caught and the program will halt (so this will not // introduce silent failures, which is good). + // DISABLE_EXCEPTION_CATCHING = 0 - generate code to actually catch exceptions + // DISABLE_EXCEPTION_CATCHING = 1 - disable exception catching at all + // DISABLE_EXCEPTION_CATCHING = 2 - disable exception catching, but enables + // catching in whitelist // TODO: Make this also remove cxa_begin_catch etc., optimize relooper // for it, etc. (perhaps do all of this as preprocessing on .ll?) + +var EXCEPTION_CATCHING_WHITELIST = []; // Enables catching exception in listed functions if + // DISABLE_EXCEPTION_CATCHING = 2 set + var EXECUTION_TIMEOUT = -1; // Throw an exception after X seconds - useful to debug infinite loops var CHECK_OVERFLOWS = 0; // Add code that checks for overflows in integer math operations. // There is currently not much to do to handle overflows if they occur. diff --git a/tests/runner.py b/tests/runner.py index b8c7369e..a3904bb6 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -2372,6 +2372,38 @@ Exception execution path of first function! 1 Settings.DISABLE_EXCEPTION_CATCHING = 0 self.do_run(src, 'Throw...Construct...Catched...Destruct...Throw...Construct...Copy...Catched...Destruct...Destruct...') + def test_white_list_exception(self): + Settings.DISABLE_EXCEPTION_CATCHING = 2 + Settings.EXCEPTION_CATCHING_WHITELIST = ["__Z12somefunctionv"] + + src = ''' + #include <stdio.h> + + void thrower() { + printf("infunc..."); + throw(99); + printf("FAIL"); + } + + void somefunction() { + try { + thrower(); + } catch(...) { + printf("done!*\\n"); + } + } + + int main() { + somefunction(); + return 0; + } + ''' + self.do_run(src, 'infunc...done!*') + + Settings.DISABLE_EXCEPTION_CATCHING = 0 + Settings.EXCEPTION_CATCHING_WHITELIST = [] + + def test_uncaught_exception(self): if self.emcc_args is None: return self.skip('no libcxx inclusion without emcc') if '-O2' in self.emcc_args: |