diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/jsifier.js | 12 | ||||
-rw-r--r-- | src/library.js | 2 | ||||
-rw-r--r-- | src/library_browser.js | 7 | ||||
-rw-r--r-- | src/modules.js | 16 | ||||
-rw-r--r-- | src/parseTools.js | 13 | ||||
-rw-r--r-- | src/preamble.js | 6 | ||||
-rw-r--r-- | src/settings.js | 5 |
7 files changed, 50 insertions, 11 deletions
diff --git a/src/jsifier.js b/src/jsifier.js index 4af522b4..ff43c8c6 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -505,7 +505,7 @@ function JSify(data, functionsOnly, givenFunctions) { item.JS = ''; } else if (LibraryManager.library.hasOwnProperty(shortident)) { item.JS = addFromLibrary(shortident); - } else { + } else if (!LibraryManager.library.hasOwnProperty(shortident + '__inline')) { item.JS = 'var ' + item.ident + '; // stub for ' + item.ident; if (WARN_ON_UNDEFINED_SYMBOLS || ASM_JS) { // always warn on undefs in asm, since it breaks validation warn('Unresolved symbol: ' + item.ident); @@ -1401,6 +1401,8 @@ function JSify(data, functionsOnly, givenFunctions) { if (ASM_JS) { assert(returnType.search(/\("'\[,/) == -1); // XXX need isFunctionType(type, out) callIdent = '(' + callIdent + ')&{{{ FTM_' + sig + ' }}}'; // the function table mask is set in emscripten.py + } else if (SAFE_DYNCALLS) { + callIdent = '(tempInt=' + callIdent + ',tempInt < 0 || tempInt >= FUNCTION_TABLE.length-1 ? abort("dyncall error") : tempInt)'; } callIdent = Functions.getTable(sig) + '[' + callIdent + ']'; } @@ -1567,9 +1569,11 @@ function JSify(data, functionsOnly, givenFunctions) { var shellParts = read(shellFile).split('{{BODY}}'); print(shellParts[1]); // Print out some useful metadata (for additional optimizations later, like the eliminator) - print('// EMSCRIPTEN_GENERATED_FUNCTIONS: ' + JSON.stringify(keys(Functions.implementedFunctions).filter(function(func) { - return IGNORED_FUNCTIONS.indexOf(func.ident) < 0; - })) + '\n'); + if (EMIT_GENERATED_FUNCTIONS) { + print('// EMSCRIPTEN_GENERATED_FUNCTIONS: ' + JSON.stringify(keys(Functions.implementedFunctions).filter(function(func) { + return IGNORED_FUNCTIONS.indexOf(func.ident) < 0; + })) + '\n'); + } PassManager.serialize(); diff --git a/src/library.js b/src/library.js index 885fe1e0..d0f73fdd 100644 --- a/src/library.js +++ b/src/library.js @@ -4533,7 +4533,7 @@ LibraryManager.library = { while ((i|0) < (num|0)) { var v1 = {{{ makeGetValueAsm('p1', 'i', 'i8', true) }}}; var v2 = {{{ makeGetValueAsm('p2', 'i', 'i8', true) }}}; - if ((v1|0) != (v2|0)) return (v1|0) > (v2|0) ? 1 : -1; + if ((v1|0) != (v2|0)) return ((v1|0) > (v2|0) ? 1 : -1)|0; i = (i+1)|0; } return 0; diff --git a/src/library_browser.js b/src/library_browser.js index e9396d69..5b19a360 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -204,7 +204,12 @@ mergeInto(LibraryManager.library, { var ctx; try { if (useWebGL) { - ctx = canvas.getContext('experimental-webgl', { alpha: false }); + ctx = canvas.getContext('experimental-webgl', { + alpha: false, +#if GL_TESTING + preserveDrawingBuffer: true +#endif + }); } else { ctx = canvas.getContext('2d'); } diff --git a/src/modules.js b/src/modules.js index 695abbe7..7f8a959b 100644 --- a/src/modules.js +++ b/src/modules.js @@ -330,6 +330,22 @@ var Functions = { } } } + if (SAFE_DYNCALLS) { + assert(!ASM_JS, 'cannot emit safe dyncalls in asm'); + for (var j = 0; j < table.length; j++) { + if (table[j] == 0) { + table[j] = "function() { abort('dyncall error') }"; + } + } + } + if (table.length > 20) { + // add some newlines in the table, for readability + var j = 10; + while (j+10 < table.length) { + table[j] += '\n'; + j += 10; + } + } var indices = table.toString().replace('"', ''); if (BUILD_AS_SHARED_LIB) { // Shared libraries reuse the parent's function table. diff --git a/src/parseTools.js b/src/parseTools.js index 7d1a7cd9..6e0d6e32 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -103,6 +103,11 @@ function isNiceIdent(ident, loose) { } } +function isJSVar(ident) { + return /^\(?[$_]?[\w$_\d ]*\)+$/.test(ident); + +} + function isStructPointerType(type) { // This test is necessary for clang - in llvm-gcc, we // could check for %struct. The downside is that %1 can @@ -988,7 +993,8 @@ function getHeapOffset(offset, type, forceAsm) { if (shifts != 0) { return '(' + offset + '>>' + shifts + ')'; } else { - return offset; + // we need to guard against overflows here, HEAP[U]8 expects a guaranteed int + return isJSVar(offset) ? offset : '(' + offset + '|0)'; } } } @@ -1393,7 +1399,8 @@ function getFastValue(a, op, b, type) { if (!(type in Runtime.FLOAT_TYPES)) { // if guaranteed small enough to not overflow into a double, do a normal multiply var bits = getBits(type) || 32; // default is 32-bit multiply for things like getelementptr indexes - if ((isNumber(a) && Math.abs(a) < TWO_TWENTY) || (isNumber(b) && Math.abs(b) < TWO_TWENTY) || bits < 32) { + // Note that we can emit simple multiple in non-asm.js mode, but asm.js will not parse "16-bit" multiple, so must do imul there + if ((isNumber(a) && Math.abs(a) < TWO_TWENTY) || (isNumber(b) && Math.abs(b) < TWO_TWENTY) || (bits < 32 && !ASM_JS)) { return '(((' + a + ')*(' + b + '))&' + ((Math.pow(2, bits)-1)|0) + ')'; // keep a non-eliminatable coercion directly on this } return 'Math.imul(' + a + ',' + b + ')'; @@ -1541,7 +1548,7 @@ function makePointer(slab, pos, allocator, type, ptr) { var ret = ''; var index = 0; while (index < array.length) { - ret = (ret ? ret + '.concat(' : '') + '[' + array.slice(index, index + chunkSize).map(JSON.stringify) + ']' + (ret ? ')' : ''); + ret = (ret ? ret + '.concat(' : '') + '[' + array.slice(index, index + chunkSize).map(JSON.stringify) + ']' + (ret ? ')\n' : ''); index += chunkSize; } return ret; diff --git a/src/preamble.js b/src/preamble.js index 05269c6e..a7731e7f 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -742,17 +742,19 @@ Module['writeArrayToMemory'] = writeArrayToMemory; {{{ unSign }}} {{{ reSign }}} -if (!Math.imul) Math.imul = function(a, b) { #if PRECISE_I32_MUL +if (!Math.imul) Math.imul = function(a, b) { var ah = a >>> 16; var al = a & 0xffff; var bh = b >>> 16; var bl = b & 0xffff; return (al*bl + ((ah*bl + al*bh) << 16))|0; +}; #else +Math.imul = function(a, b) { return (a*b)|0; // fast but imprecise -#endif }; +#endif // A counter of dependencies for calling run(). If we need to // do asynchronous work before running, increment this and diff --git a/src/settings.js b/src/settings.js index df9da926..308afddc 100644 --- a/src/settings.js +++ b/src/settings.js @@ -128,6 +128,8 @@ var SAFE_HEAP = 0; // Check each write to the heap, for example, this will give // that 3 is the option you usually want here. var SAFE_HEAP_LOG = 0; // Log out all SAFE_HEAP operations +var SAFE_DYNCALLS = 0; // Show stack traces on missing function pointer/virtual method calls + var ASM_HEAP_LOG = 0; // Simple heap logging, like SAFE_HEAP_LOG but cheaper, and in asm.js var CORRUPTION_CHECK = 0; // When enabled, will emit a buffer area at the beginning and @@ -158,6 +160,7 @@ var SOCKET_DEBUG = 0; // Log out socket/network data transfer. var GL_DEBUG = 0; // Print out all calls into WebGL. As with LIBRARY_DEBUG, you can set a runtime // option, in this case GL.debug. +var GL_TESTING = 0; // When enabled, sets preserveDrawingBuffer in the context, to allow tests to work (but adds overhead) var GL_MAX_TEMP_BUFFER_SIZE = 2097152; // How large GL emulation temp buffers are var GL_UNSAFE_OPTS = 1; // Enables some potentially-unsafe optimizations in GL emulation code @@ -326,6 +329,8 @@ var EXPLICIT_ZEXT = 0; // If 1, generate an explicit conversion of zext i1 to i3 var NECESSARY_BLOCKADDRS = []; // List of (function, block) for all block addresses that are taken. +var EMIT_GENERATED_FUNCTIONS = 0; // whether to emit the list of generated functions, needed for external JS optimization passes + // Compiler debugging options var DEBUG_TAGS_SHOWING = []; // Some useful items: |