aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-09-03 15:57:31 -0700
committerAlon Zakai <alonzakai@gmail.com>2013-09-03 15:57:31 -0700
commit6eaaebf4dd9c1dbd38dba929199cd3121b666c0f (patch)
tree2f61c2a85666b57fa3e03e47d6f6251623ec0ab9
parent1b458cf9c55c1ad4f74f1d3332d163e506baf4e7 (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-xemscripten.py3
-rw-r--r--src/jsifier.js12
-rw-r--r--tools/shared.py21
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