aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-08-28 18:12:53 -0700
committerAlon Zakai <alonzakai@gmail.com>2013-09-03 14:41:29 -0700
commitc76946b2f3cebf00a5e24c9582eb9b59f1039a6d (patch)
tree26754c6f7429e6a502e222f5d44be31980a87503
parentaa1c42a298a568f2910cb0a184824763016ce64f (diff)
support function pointer calls across asm modules by passing them all through invoke (for now), and have a global function table in the Runtime, which modules register their functions to
-rwxr-xr-xemscripten.py19
-rw-r--r--src/jsifier.js1
-rw-r--r--src/library.js11
-rw-r--r--src/runtime.js28
-rw-r--r--src/shell_sharedlib.js3
-rw-r--r--tests/test_core.py15
6 files changed, 60 insertions, 17 deletions
diff --git a/emscripten.py b/emscripten.py
index c3e51c96..0a13d7ad 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -631,8 +631,10 @@ Runtime.stackRestore = function(top) { asm['stackRestore'](top) };
if settings.get('DLOPEN_SUPPORT'):
funcs_js.append('''
- asm.maxFunctionIndex = %d;
-''' % max_mask)
+ asm.maxFunctionIndex = %(max_mask)d;
+ Runtime.registerFunctions(asm, %(max_mask)d+1, %(sigs)s, Module);
+ Module.SYMBOL_TABLE = SYMBOL_TABLE;
+''' % { 'max_mask': max_mask, 'sigs': str(map(str, last_forwarded_json['Functions']['tables'].keys())) })
for sig in last_forwarded_json['Functions']['tables'].iterkeys():
funcs_js.append(' var F_BASE_%s = %s;\n' % (sig, 'FUNCTION_TABLE_OFFSET' if settings.get('SIDE_MODULE') else '0'))
@@ -650,13 +652,18 @@ Runtime.stackRestore = function(top) { asm['stackRestore'](top) };
symbol_table = {}
for k, v in forwarded_json['Variables']['indexedGlobals'].iteritems():
if forwarded_json['Variables']['globals'][k]['named']:
- symbol_table[k] = v + forwarded_json['Runtime']['GLOBAL_BASE']
+ symbol_table[k] = str(v + forwarded_json['Runtime']['GLOBAL_BASE'])
for raw in last_forwarded_json['Functions']['tables'].itervalues():
if raw == '': continue
table = map(string.strip, raw[raw.find('[')+1:raw.find(']')].split(","))
- symbol_table.update(map(lambda x: (x[1], x[0]),
- filter(lambda x: x[1] != '0', enumerate(table))))
- outfile.write("var SYMBOL_TABLE = %s;" % json.dumps(symbol_table))
+ for i in range(len(table)):
+ value = table[i]
+ if value != '0':
+ if settings.get('SIDE_MODULE'):
+ symbol_table[value] = 'FUNCTION_TABLE_OFFSET+' + str(i)
+ else:
+ symbol_table[value] = str(i)
+ outfile.write("var SYMBOL_TABLE = %s;" % json.dumps(symbol_table).replace('"', ''))
for funcs_js_item in funcs_js: # do this loop carefully to save memory
funcs_js_item = indexize(funcs_js_item)
diff --git a/src/jsifier.js b/src/jsifier.js
index 3a87df45..c3ba6e74 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -1406,6 +1406,7 @@ function JSify(data, functionsOnly, givenFunctions) {
assert(ident != 'asm', 'Inline assembly cannot be compiled to JavaScript!');
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
ident = Variables.resolveAliasToIdent(ident);
var shortident = ident.slice(1);
diff --git a/src/library.js b/src/library.js
index c160c785..25251299 100644
--- a/src/library.js
+++ b/src/library.js
@@ -5050,11 +5050,11 @@ LibraryManager.library = {
try {
var lib_module = eval(lib_data)(
#if ASM_JS
- asm.maxFunctionIndex,
- Module
+ Runtime.functionTable.length,
#else
- {{{ Functions.getTable('x') }}}.length
+ {{{ Functions.getTable('x') }}}.length,
#endif
+ Module
);
} catch (e) {
#if ASSERTIONS
@@ -5132,7 +5132,12 @@ LibraryManager.library = {
} else {
var result = lib.module[symbol];
if (typeof result == 'function') {
+#if ASM_JS
+ result = lib.module.SYMBOL_TABLE[symbol];
+ assert(result);
+#else
result = Runtime.addFunction(result);
+#endif
lib.cached_functions = result;
}
return result;
diff --git a/src/runtime.js b/src/runtime.js
index 33088ad9..e42f90e3 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -384,6 +384,34 @@ var Runtime = {
return Runtime.funcWrappers[func];
},
+#if DLOPEN_SUPPORT
+ functionTable: [], // will contain objects mapping sigs to js functions that call into the right asm module with the right index
+
+ registerFunctions: function(asm, num, sigs, jsModule) {
+ // use asm module dynCall_* from functionTable
+ if (num % 2 == 1) num++; // keep pointers even
+ var table = Runtime.functionTable;
+ var from = table.length;
+ assert(from % 2 == 0);
+ for (var i = 0; i < num; i++) {
+ table[from + i] = {};
+ sigs.forEach(function(sig) { // TODO: new Function etc.
+ var full = 'dynCall_' + sig;
+ table[from + i][sig] = function() {
+ arguments[i] -= from;
+ return asm[full].apply(null, arguments);
+ }
+ });
+ }
+ // patch js module dynCall_* to use functionTable
+ sigs.forEach(function(sig) {
+ jsModule['dynCall_' + sig] = function() {
+ return table[arguments[0]][sig].apply(null, arguments);
+ };
+ });
+ },
+#endif
+
// Returns a processor of UTF.
// processCChar() receives characters from a C-like UTF representation and returns JS string fragments.
// See RFC3629 for details, the bytes are assumed to be valid UTF-8
diff --git a/src/shell_sharedlib.js b/src/shell_sharedlib.js
index 505c3d7b..a2956c24 100644
--- a/src/shell_sharedlib.js
+++ b/src/shell_sharedlib.js
@@ -3,6 +3,8 @@
var Module = {};
var args = [];
Module.arguments = [];
+ Module.print = parentModule.print;
+ Module.printErr = parentModule.printErr;
{{BODY}}
@@ -10,3 +12,4 @@
return Module;
});
+
diff --git a/tests/test_core.py b/tests/test_core.py
index c6b1a69e..4871eef1 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -5714,6 +5714,13 @@ def process(filename):
CMP_TYPE lib_cmp_ptr;
int arr[5] = {4, 2, 5, 1, 3};
+ qsort((void*)arr, 5, sizeof(int), main_cmp);
+ printf("Sort with main comparison: ");
+ for (int i = 0; i < 5; i++) {
+ printf("%d ", arr[i]);
+ }
+ printf("\\n");
+
lib_handle = dlopen("liblib.so", RTLD_NOW);
if (lib_handle == NULL) {
printf("Could not load lib.\\n");
@@ -5725,14 +5732,6 @@ def process(filename):
return 1;
}
lib_cmp_ptr = getter_ptr();
-
- qsort((void*)arr, 5, sizeof(int), main_cmp);
- printf("Sort with main comparison: ");
- for (int i = 0; i < 5; i++) {
- printf("%d ", arr[i]);
- }
- printf("\\n");
-
qsort((void*)arr, 5, sizeof(int), lib_cmp_ptr);
printf("Sort with lib comparison: ");
for (int i = 0; i < 5; i++) {