diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-08-28 18:12:53 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-09-03 14:41:29 -0700 |
commit | c76946b2f3cebf00a5e24c9582eb9b59f1039a6d (patch) | |
tree | 26754c6f7429e6a502e222f5d44be31980a87503 | |
parent | aa1c42a298a568f2910cb0a184824763016ce64f (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-x | emscripten.py | 19 | ||||
-rw-r--r-- | src/jsifier.js | 1 | ||||
-rw-r--r-- | src/library.js | 11 | ||||
-rw-r--r-- | src/runtime.js | 28 | ||||
-rw-r--r-- | src/shell_sharedlib.js | 3 | ||||
-rw-r--r-- | tests/test_core.py | 15 |
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++) { |