diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-09-03 15:57:31 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-09-03 15:57:31 -0700 |
commit | 6eaaebf4dd9c1dbd38dba929199cd3121b666c0f (patch) | |
tree | 2f61c2a85666b57fa3e03e47d6f6251623ec0ab9 | |
parent | 1b458cf9c55c1ad4f74f1d3332d163e506baf4e7 (diff) |
add extCall_* methods in asm dlopen support, parallel to invoke in that they are able to access other modules, but do not catch exceptions
-rwxr-xr-x | emscripten.py | 3 | ||||
-rw-r--r-- | src/jsifier.js | 12 | ||||
-rw-r--r-- | tools/shared.py | 21 |
3 files changed, 31 insertions, 5 deletions
diff --git a/emscripten.py b/emscripten.py index 2e727d51..257527fe 100755 --- a/emscripten.py +++ b/emscripten.py @@ -483,6 +483,9 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None, shared.Settings.copy(settings) asm_setup += '\n' + shared.JS.make_invoke(sig) + '\n' basic_funcs.append('invoke_%s' % sig) + if settings.get('DLOPEN_SUPPORT'): + asm_setup += '\n' + shared.JS.make_extcall(sig) + '\n' + basic_funcs.append('extCall_%s' % sig) # calculate exports exported_implemented_functions = list(exported_implemented_functions) diff --git a/src/jsifier.js b/src/jsifier.js index ce08fdde..8592364d 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1405,8 +1405,10 @@ function JSify(data, functionsOnly, givenFunctions) { // We cannot compile assembly. See comment in intertyper.js:'Call' assert(ident != 'asm', 'Inline assembly cannot be compiled to JavaScript!'); + var extCall = false; + if (ASM_JS && funcData.setjmpTable) forceByPointer = true; // in asm.js mode, we must do an invoke for each call - if (ASM_JS && DLOPEN_SUPPORT) invoke = true; // go through invoke so we can access other modules TODO: optimize + if (ASM_JS && DLOPEN_SUPPORT && !invoke) extCall = true; // go out, to be able to access other modules TODO: optimize ident = Variables.resolveAliasToIdent(ident); var shortident = ident.slice(1); @@ -1467,7 +1469,7 @@ function JSify(data, functionsOnly, givenFunctions) { args = args.map(function(arg, i) { return indexizeFunctions(arg, argsTypes[i]) }); if (ASM_JS) { - if (shortident in Functions.libraryFunctions || simpleIdent in Functions.libraryFunctions || byPointerForced || invoke || funcData.setjmpTable) { + if (shortident in Functions.libraryFunctions || simpleIdent in Functions.libraryFunctions || byPointerForced || invoke || extCall || funcData.setjmpTable) { args = args.map(function(arg, i) { return asmCoercion(arg, argsTypes[i]) }); } else { args = args.map(function(arg, i) { return asmEnsureFloat(arg, argsTypes[i]) }); @@ -1558,16 +1560,16 @@ function JSify(data, functionsOnly, givenFunctions) { if (ASM_JS) { assert(returnType.search(/\("'\[,/) == -1); // XXX need isFunctionType(type, out) Functions.neededTables[sig] = 1; - var functionTableCall = !byPointerForced && !funcData.setjmpTable && !invoke; + var functionTableCall = !byPointerForced && !funcData.setjmpTable && !invoke && !extCall; if (functionTableCall) { // normal asm function pointer call callIdent = '(' + callIdent + ')&{{{ FTM_' + sig + ' }}}'; // the function table mask is set in emscripten.py } else { - // This is a call through an invoke_*, either a forced one, or a setjmp-required one + // This is a call through an invoke_* or extCall, either a forced one, or a setjmp-required one // note: no need to update argsTypes at this point if (byPointerForced) Functions.unimplementedFunctions[callIdent] = sig; args.unshift(byPointerForced ? Functions.getIndex(callIdent, sig) : asmCoercion(callIdent, 'i32')); - callIdent = 'invoke_' + sig; + callIdent = (extCall ? 'extCall' : 'invoke') + '_' + sig; } } else if (SAFE_DYNCALLS) { assert(!ASM_JS, 'cannot emit safe dyncalls in asm'); diff --git a/tools/shared.py b/tools/shared.py index aecf0799..b0b3985e 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -1443,6 +1443,27 @@ class JS: return ident.replace('%', '$').replace('@', '_') @staticmethod + def make_extcall(sig, named=True): + args = ','.join(['a' + str(i) for i in range(1, len(sig))]) + args = 'index' + (',' if args else '') + args + # C++ exceptions are numbers, and longjmp is a string 'longjmp' + ret = '''function%s(%s) { + %sModule["dynCall_%s"](%s); +}''' % ((' extCall_' + sig) if named else '', args, 'return ' if sig[0] != 'v' else '', sig, args) + + if Settings.DLOPEN_SUPPORT and Settings.ASSERTIONS: + # guard against cross-module stack leaks + ret = ret.replace(') {\n', ''') { + try { + var preStack = asm.stackSave(); +''').replace(';\n}', '''; + } finally { + assert(asm.stackSave() == preStack); + } +}''') + return ret + + @staticmethod def make_invoke(sig, named=True): args = ','.join(['a' + str(i) for i in range(1, len(sig))]) args = 'index' + (',' if args else '') + args |