diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-04-22 20:38:00 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-04-22 20:38:00 -0700 |
commit | 40edec0ec80f07b5ce2e351e67137f7908a0ea1e (patch) | |
tree | c333f1238f2084916652baa72be7a03666331fa6 | |
parent | 29a9d8b2c5d5032ef6c980b5256982f66ac23d5b (diff) |
use invoke when doing a setjmp-guarding call via a function pointer
-rw-r--r-- | src/jsifier.js | 11 | ||||
-rwxr-xr-x | tests/runner.py | 35 |
2 files changed, 41 insertions, 5 deletions
diff --git a/src/jsifier.js b/src/jsifier.js index a01b2655..3d2d022b 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1448,20 +1448,21 @@ function JSify(data, functionsOnly, givenFunctions) { var sig = Functions.getSignature(returnType, argsTypes, hasVarArgs); if (ASM_JS) { assert(returnType.search(/\("'\[,/) == -1); // XXX need isFunctionType(type, out) - if (!byPointerForced) { + if (!byPointerForced && !funcData.setjmpTable) { + // normal asm function pointer call callIdent = '(' + callIdent + ')&{{{ FTM_' + sig + ' }}}'; // the function table mask is set in emscripten.py } else { - // This is a forced call, through an invoke_*. + // This is a call through an invoke_*, either a forced one, or a setjmp-required one // note: no need to update argsTypes at this point - Functions.unimplementedFunctions[callIdent] = sig; - args.unshift(byPointerForced ? Functions.getIndex(callIdent) : callIdent); + if (byPointerForced) Functions.unimplementedFunctions[callIdent] = sig; + args.unshift(byPointerForced ? Functions.getIndex(callIdent) : asmCoercion(callIdent, 'i32')); callIdent = 'invoke_' + sig; } } else if (SAFE_DYNCALLS) { assert(!ASM_JS, 'cannot emit safe dyncalls in asm'); callIdent = '(tempInt=' + callIdent + ',tempInt < 0 || tempInt >= FUNCTION_TABLE.length-1 || !FUNCTION_TABLE[tempInt] ? abort("dyncall error: ' + sig + ' " + FUNCTION_TABLE_NAMES[tempInt]) : tempInt)'; } - if (!byPointerForced) callIdent = Functions.getTable(sig) + '[' + callIdent + ']'; + if (!ASM_JS || (!byPointerForced && !funcData.setjmpTable)) callIdent = Functions.getTable(sig) + '[' + callIdent + ']'; } var ret = callIdent + '(' + args.join(', ') + ')'; diff --git a/tests/runner.py b/tests/runner.py index 2e01226f..33a2ef67 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -2489,6 +2489,41 @@ Calling longjmp the second time! Exception execution path of first function! 1 ''') + def test_longjmp_funcptr(self): + src = r''' + #include <stdio.h> + #include <setjmp.h> + + static jmp_buf buf; + + void (*fp)() = NULL; + + void second(void) { + printf("second\n"); // prints + longjmp(buf,1); // jumps back to where setjmp was called - making setjmp now return 1 + } + + void first(void) { + fp(); + printf("first\n"); // does not print + } + + int main(int argc, char **argv) { + fp = argc == 200 ? NULL : second; + + volatile int x = 0; + if ( ! setjmp(buf) ) { + x++; + first(); // when executed, setjmp returns 0 + } else { // when longjmp jumps back, setjmp returns 1 + printf("main: %d\n", x); // prints + } + + return 0; + } + ''' + self.do_run(src, 'second\nmain: 1\n') + def test_setjmp_many(self): src = r''' #include <stdio.h> |